# transparenz bei png bildern beibehalten



## mephi (11. Mai 2007)

Hi, ich hab mal eine Frage.. geht die transparenz bei png bildern immer verloren wenn ich sie mit als BufferedImage einlese bzw welche fehler kann man machen dass die transparenz verloren geht?

hab hier fremden code vor mir indem ich den fehler beheben muss dass pngs ihre transparenz verlieren. ich denke alles zu posten wäre etwas viel um da durch zu blicken, deswegen die allgemeine frage.

die bilder werden fürs cachen gespeichert und haben da schon ihre transparenz verloren.. ich denke folgende methode ist schuld..


```
protected void saveImageData(PersistCacheKey key, BufferedImage bi, ImageWriter writer)
	{
		if (persistentImageCache == null)
		{
			// no cache wanted
			return;
		}

		synchronized (persistentImageCache)
		{

			File cachedImage = new File(persistentImageCache, key.getKey());

			try
			{
				ImageOutputStream os = null;

				try
				{
					writer.reset();
					os = ImageIO.createImageOutputStream(new FileOutputStream(cachedImage, false));
					writer.setOutput(os);
					writer.write(bi);
				}
				finally
				{
					if (os != null)
					{
						os.close();
					}
				}
			}
			catch (IOException e)
			{
				log.error("failed during save", e);
				if (cachedImage.exists())
				{
					cachedImage.delete();
				}
			}
		}
	}
```


----------



## Wildcard (11. Mai 2007)

Von welchem Typ ist das BufferedImage?


----------



## mephi (11. Mai 2007)

bi.getType() liefert mit den int wert 13 zurück
aus der api werd ich aber nicht schlau welcher typ das ist


----------



## Wildcard (11. Mai 2007)

Kann ich dir so auch nicht sagen. Schau mal im Source...


----------



## mephi (11. Mai 2007)

```
/**
     * Represents an indexed byte image.  When this type is used as the
     * <code>imageType</code> argument to the <code>BufferedImage</code>
     * constructor that takes an <code>imageType</code> argument
     * but no <code>ColorModel</code> argument, an 
     * <code>IndexColorModel</code> is created with
     * a 256-color 6/6/6 color cube palette with the rest of the colors
     * from 216-255 populated by grayscale values in the
     * default sRGB ColorSpace.
     *
     * 

 When color data is stored in an image of this type,
     * the closest color in the colormap is determined 
     * by the <code>IndexColorModel</code> and the resulting index is stored.
     * Approximation and loss of alpha or color components
     * can result, depending on the colors in the 
     * <code>IndexColorModel</code> colormap.
     */
    public static final int TYPE_BYTE_INDEXED = 13;
```


----------



## Wildcard (11. Mai 2007)

mephi hat gesagt.:
			
		

> ```
> *
> 
> When color data is stored in an image of this type,
> ...


Das sagt doch wohl alles  :wink: 
Nimm ein BufferedImage vom Typ ARGB oder so.


----------



## mephi (11. Mai 2007)

macht das unterschiede bei der performance? wenn nicht nehm ich das gleich für alle bilder egal welches format. das machts einfacher 


edit:
wie nehm ich denn ein BufferedImage ohne die höhe und breite zu kennen? die konstruktoren wollen ja unbedingt die höhe und breite zum imagetype haben


----------



## Wildcard (11. Mai 2007)

Ja. Unter Umständen sogar einen großen Unterschied.
Echte PNG Transparenz wird im Gegensatz du Bitmaskentransparenz (gif) nicht Hardware Beschleunigt.


----------



## mephi (11. Mai 2007)

hier mal die service methode des sevlets.. weiß garnicht so recht wo ich da ansetzen soll.. wenn er ein image findet das "gecached" wurde dann ist es zu spät.. sehe da aber nicht was passiert wenn er keins findet bekommt er nämlich bei ..

InputStream cachedImageData = findPersistentImageData(persistCacheKey);

null zurück



```
File cachedImage = new File(persistentImageCache, key.getKey());
			if (!cachedImage.exists())
			{
				return null;
			}
```


```
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
	{
		String page = engine.safeGetParameter(req, HDR_NAME);
		String version = engine.safeGetParameter(req, HDR_VERSION);
		String type = engine.safeGetParameter(req, ImagePro.PARAM_TYPE);
		String rotate = engine.safeGetParameter(req, ImagePro.PARAM_ROTATE);
		wikiSession = WikiSession.getWikiSession(engine, req);

		int rotateBy = 0;
		try
		{
			rotateBy = (Integer.parseInt(rotate) / 90) % 4;
		}
		catch (NumberFormatException e)
		{
			rotateBy = 0;
		}

		int imageWidth = 0;
		boolean hasImageWidth = false;
		int imageHeight = 0;
		boolean hasImageHeight = false;

		try
		{  
			String imageWidthTemp = engine.safeGetParameter(req, ImagePro.PARAM_WIDTH);
			if(imageWidthTemp.equals("thumb")) imageWidth = sizeThumb;
			else if(imageWidthTemp.equals("small")) imageWidth = sizeSmall;
			else if(imageWidthTemp.equals("medium")) imageWidth = sizeMedium;
			else if(imageWidthTemp.equals("large"))	imageWidth = sizeLarge;
			else imageWidth = Integer.parseInt(imageWidthTemp);

			hasImageWidth = true;
		}
		catch (NumberFormatException e)
		{
			;
		}

		try
		{
			imageHeight = Integer.parseInt(engine.safeGetParameter(req, ImagePro.PARAM_HEIGHT));
			hasImageHeight = true;
		}
		catch (NumberFormatException e)
		{
			;
		}

		String msg = "An error occurred. Ouch.";
		int ver = WikiProvider.LATEST_VERSION;

		AttachmentManager mgr = engine.getAttachmentManager();
		AuthorizationManager authmgr = engine.getAuthorizationManager();
		UserProfile wup = engine.getUserManager().getUserProfile(wikiSession);

		if (page == null)
		{
			msg = "Invalid attachment name.";
		}
		else
		{
			try
			{
				if (version != null)
				{
					ver = Integer.parseInt(version);
				}

				Attachment att = mgr.getAttachmentInfo(page, ver);
				
				Permission permission = new PagePermission( att, "view" );
				if (att != null)
				{
					//
					//  Check if the user has permission for this attachment
					//

					if (!authmgr.checkPermission(wikiSession, permission))
					{
						if (log.isDebugEnabled())
						{
							log.debug("User does not have permission for this");
						}
						res.sendError(HttpServletResponse.SC_FORBIDDEN);
						return;
					}

					//
					//  Check if the client already has a version of this attachment.
					//
					if (checkFor304(req, att))
					{
						if (log.isDebugEnabled())
						{
							log.debug("Client has latest version already, sending 304...");
						}
						res.sendError(HttpServletResponse.SC_NOT_MODIFIED);
						return;
					}

					String mimetype;
					if (type != null)
					{
						mimetype = type;
					}
					else
					{
						mimetype = getServletConfig().getServletContext().getMimeType(att.getFileName().toLowerCase());
						if (mimetype == null)
						{
							mimetype = "application/binary";
						}
					}

					PersistCacheKey persistCacheKey = new PersistCacheKey(imageWidth, imageHeight, rotateBy, mimetype, att);
					InputStream cachedImageData = findPersistentImageData(persistCacheKey);
					if (cachedImageData != null)
					{
						if (log.isDebugEnabled())
						{
							log.debug("PERSIST_IMAGE_CACHE_HIT " + att.getFileName());
						}

						byte[] buf = new byte[8192];
						int read;

						sendHeader(res, mimetype, att);

						OutputStream os = null;
						try
						{
							os = res.getOutputStream();
							while ((read = cachedImageData.read(buf, 0, buf.length)) > -1)
							{
								os.write(buf, 0, read);
							}
						}
						finally
						{
							if (os != null)
							{
								os.close();
							}
						}
						return;
					}
					else
					{
						if (log.isDebugEnabled())
						{
							log.debug("PERSIST_IMAGE_CACHE_MISS " + att.getFileName());
						}
					}


					//
					//  We use 'inline' instead of 'attachment' so that user agents
					//  can try to automatically open the file.
					//

					Iterator iterImageWriters = ImageIO.getImageWritersByMIMEType(mimetype);
					if (!iterImageWriters.hasNext())
					{
						msg = "no imagewriter found for mimetype " + mimetype;
					}
					else
					{
						ImageWriter imageWriter = (ImageWriter) iterImageWriters.next();

						sendHeader(res, mimetype, att);

						// TODO res.setContentLength((int) att.getSize());

						ImageOutputStream os = null;
						try
						{

							CacheEntry cacheEntry = findInMemroyImageData(mgr, att);
							BufferedImage bi = cacheEntry.image;

                            BufferedImage biNew = transformImage(bi, rotateBy, hasImageHeight, imageHeight, hasImageWidth, imageWidth);


                            saveImageData(persistCacheKey, biNew, imageWriter);

							os = ImageIO.createImageOutputStream(res.getOutputStream());

							try
							{
								imageWriter.reset();
								imageWriter.setOutput(os);
								imageWriter.write(biNew);
							}
							finally
							{
								imageWriter.dispose();
							}
						}
						finally
						{
							if (os != null)
							{
								os.close();
							}
						}


						if (log.isDebugEnabled())
						{
							msg = "Attachment " + att.getFileName() + " sent to " + req.getRemoteUser() + " on " + req.getRemoteHost();
							if (log.isDebugEnabled())
							{
								log.debug(msg);
							}
						}

						msg = "";
					}
				}
				else
				{
					msg = "Attachment '" + page + "', version " + ver +
						" does not exist.";
				}
			}
			catch (ProviderException pe)
			{
				msg = "Provider error: " + pe.getMessage();
			}
			catch (NumberFormatException nfe)
			{
				msg = "Invalid version number (" + version + ")";
			}
			catch (IOException ioe)
			{
				msg = "Error: " + ioe.getMessage();
			}
		}

		if (msg != null && msg.length() > 0)
		{
			log.info(msg);
		}
	}
```


----------



## mephi (13. Mai 2007)

ich denke ich habe nun die stelle an der der fehler ist..
das bild wird eingelesen mit


```
InputStream is = mgr.getAttachmentStream(att);
BufferedImage bi = ImageIO.read(is);
```
so geht die info dass es ein png ist verloren


```
is = mgr.getAttachmentStream(att);
					mimeType = getServletConfig().getServletContext().getMimeType(att.getFileName().toLowerCase()); 
					Iterator<ImageReader> imageReaders = ImageIO.getImageReadersByMIMEType(mimeType);
					ImageReader imageReader = imageReaders.next();
                // bi= ? was kommt hier her?
```
mir ist nur unklar wie ich nun ein BuffededImage aus dem imageReader erhalte..

imageReader.setInput(is); aber wie weiter?


----------



## mephi (13. Mai 2007)

ok das hat mir eben jemand geschickt.. aber das bringt mich eher zum weinen..


```
// new entry
				InputStream is = null;
				BufferedImage bi;
				String mimeType= null;
            is = mgr.getAttachmentStream(att);
				System.out.println("identifying imagetype...");
				try
				{
					System.out.println("image/png identified");
					mimeType = getServletConfig().getServletContext().getMimeType(att.getFileName().toLowerCase());
					if( mimeType.equalsIgnoreCase("image/png")) {
						ImageInputStream iis = ImageIO.createImageInputStream(is);
						Iterator<ImageReader> imageReaders = ImageIO.getImageReadersByMIMEType(mimeType);
						ImageReader imageReader = imageReaders.next();
						imageReader.setInput(iis);
						bi = imageReader.read(0);
						System.out.println(bi.getType());
					}
					else {
						System.out.println("no image/png identified");
						bi = ImageIO.read(is);
						
					}
					
					
				}
```

und jetzt gibt er mir als imagetype wieder 13 aus .. also nur RGB.. 

bin mit meinem latein am ende..
habe doch extra den richtigen imagereader mit dem passenden mimetype ausgesucht.. wo geht denn der a kanal verloren? oder warum?


----------



## mephi (14. Mai 2007)

so eben mal ein anderes png bild getestet das funktioniert wunderbar.. ist auch ein anderer farbtyp. 0 2 oder 5


solang ich keine transformationen an dem png mit 13 vornehm ist auch wieder transparent bei ausgabe nur wenn ich funktionen von Graphics2D anwende geht die transparenz verloren..
das ist ärgerlich..


----------

