FormatFa

导航

安卓版的pvr图片查看

public class PVRTDecompress
{
	/*
	 author:FormatFa
	 mail :1758759399@qq.com
	 date :2017-6-14
	 */



	//modify from PVRTDecompress.cpp in PowerVR
	//https://github.com/gildor2/UModel libs dir


	public static int Version3 = 0x03525650;

	static int ETC_FLIP = 0x01000000;
	static int ETC_DIFF = 0x02000000;


	static int[][] mod= new int[][]{
		{2, 8, -2, -8},
		{5, 17, -5, -17},
		{9, 29, -9, -29},
		{13, 42, -13, -42},
		{18, 60, -18, -60},
		{24, 80, -24, -80},
		{33, 106, -33, -106},
		{47, 183, -47, -183}
	};


	/*
	 PvrtHeader info from PVR File Format  Specification.pdf

	 */
	public static int flag_NoFlag=0x0;
	//When this flag is set, colour values within the texture have  been pre- multiplied by the alpha values

	public static	int flag_premultiplied=0x02;


	//Texture data is in the Linear RGB colour space 
	public static int colorSpace_LinearRGB=0;
	//Texture data is in the Standard RGB colour space
public static 	int colorSpace_aRGB=1;
public static 	int channel_UnsignedByteNormalised=0;
	
public static long format_ETC2_RGB=0x00000016;


	public static class PVRTHeader
	{
		public	int version;
		public	int flags;
		public	long pixelFormat;
		//int piexlFormat2;
		public	int colorSpace;
		public	int channelType;
		public	int width;
		public	int heigth;
		public int depth;
		public	int numSurface;
		public	int numFace;
		public	int minMapCount;
		public	int metaDataSize;

		public byte[] imgdata;

		@Override
		public String toString()
		{

			return "version:"+Integer.toHexString(version)
				+"\nflag:"+Integer.toHexString(flags)
				+"\npiex:"+Long.toHexString(pixelFormat)
				+"\ncolor:"+Integer.toHexString(colorSpace)
				+"\nchannal:"+Integer.toHexString(channelType)
				+"\nwdth:"+Integer.toHexString(width)
				+"\nheigth:"+Integer.toHexString(heigth)
				+"\nsurface:"+Integer.toHexString(numSurface)
				+"\nface:"+Integer.toHexString(numFace)
				+"\nminp:"+Integer.toHexString(minMapCount)
				+"\nmeta:"+Integer.toHexString(metaDataSize);



		}

	}


	void pri(int l)
	{


	}

	public  static PVRTHeader loadPVRHeader(InputStream is) throws Exception
	{

		PVRTHeader head = new PVRTHeader();

		//if(head.version!=Version3)
		//  throw new Exception("magic except:"+Integer.toHexString(head.version);

		MyDataInputStream my = new MyDataInputStream(is);
		
		head.version = my.readInt();
		
		head.flags = my.readInt();
		
		head.pixelFormat = my.readLong();
		
		head.colorSpace = my.readInt();
		
		head.channelType = my.readInt();
		head.width = my.readInt();
		head.heigth= my.readInt();
		head.depth = my.readInt();
		head.numSurface = my.readInt();
		head.numFace = my.readInt();
		head.minMapCount = my.readInt();
		head.metaDataSize = my.readInt();
 
		is.skip(head.metaDataSize);
		byte[] data = new byte[my.available()];
		my.readFully(data);

		head.imgdata = data;
		return head;

	}

	public static int[] PVRTDecompressETC_int(PVRTHeader head)
	{


		List<Integer> t=new ArrayList<Integer>();
		
		int[] piex=new int[head.width*head.heigth];

		long blockTop,blockBot;
		long modtable1,modtable2;

		boolean bFlip,bDiff;

		char red1,green1,blue1;
		char red2,green2,blue2;



		int offset=0;
		int mark = 0;

		int w = head.width;
		int h = head.heigth;

		byte[] data = head.imgdata;


		for(int i = 0 ; i < h;i+=4)
		{

			for(int j = 0; j<w;j+=4)
			{

				int p = offset;
				mark = i*w+j;

				blockTop = ByteUtils.byte2intLow(new byte[]{data[p],data[p+1],data[p+2],data[p+3]});
				blockBot = ByteUtils.byte2intLow(new byte[]{data[p+4],data[p+5],data[p+6],data[p+7]});
				//	System.out.println(Integer.toHexString((int)blockTop)+" "+Integer.toHexString((int)blockBot));

				offset+=8;

				bFlip = ((blockTop&ETC_FLIP)!=0);
				bDiff = (blockTop&ETC_DIFF)!=0;


				if(bDiff)
				{

					blue1 =(char) ((blockTop & 0xf80000) >> 16);
					green1 = (char)((blockTop & 0xf800) >> 8);
					red1 = (char)(blockTop & 0xf8);
				//	System.out.println("greeqn:"+(int)green1+",:"+(int)blue1+","+(int)red1);
					
					//in c is signed char,
					// get differential colour for subblock 2
					char blues =	(char)((blue1 >> 3) +(char)	(((blockTop & 0x70000) >> 11) >> 5));
					char greens=(   (char)(  (green1 >> 3 )+   (  ((blockTop & 0x700) >> 3) >> 5)));
					
					char reds =(char)(  (red1 >> 3) +     (   ((blockTop & 0x7) << 5) >> 5));
			//		System.out.println("b:"+blockTop+  "sgreeqn:"+(int)greens+",:"+(int)blues+","+(int)reds);
					
					blue2 = blues;
					green2 = greens;
					red2 = reds;
					if(offset<120&&bFlip)
//							
						System.out.println( (int)red1+"trs:"+(int)reds+"-- "+blockTop+    "_yes:"+ (int)red2+","+(int)green2+","+(int) blue2);
//
					red1 =(char)( red1 + (red1 >> 5)); // copy bits to lower sig
					green1  = (char)( green1 + (green1 >> 5)); // copy bits to lower sig
					blue1 = (char)( blue1 + (blue1 >> 5)); // copy bits to lower sig

					red2 = (char)( (red2 << 3) + (red2 >> 2)); // copy bits to lower sig
					green2 = (char)( (green2 << 3) + (green2 >> 2)); // copy bits to lower sig
					blue2 =  (char)( (blue2 << 3) + (blue2 >> 2)); // copy bits to lower sig
					
				}
				else
				{
    //System.out.println("diff");
					// individual mode 4 + 4 colour bits
					// get base colour for subblock 1
					blue1 =(char) ((blockTop & 0xf00000) >> 16);
					blue1 =(char) ( blue1 + (blue1 >> 4)); // copy bits to lower sig
					green1 =(char) (int)((blockTop & 0xf000) >> 8);
					green1 =(char) ( green1 + (green1 >> 4)); // copy bits to lower sig
					red1 = (char) (int)(blockTop & 0xf0);
					red1 =(char) (red1 + (red1 >> 4)); // copy bits to lower sig

					// get base colour for subblock 2
					blue2 =(char) (int)((blockTop & 0xf0000) >> 12);
					blue2 = (char)( blue2 + (blue2 >> 4)); // copy bits to lower sig
					green2 =(char) (int)((blockTop & 0xf00) >> 4);
					green2 = (char)(green2 + (green2 >> 4)); // copy bits to lower sig
					red2 =(char)(int) ((blockTop & 0xf) << 4);
					red2 = (char)(red2 + (red2 >> 4)); // copy bits to lower sig
				//	System.out.println("b:"+blockTop+"greeqn:"+(int)green2+",:"+(int)blue2+","+(int)red2);
					
				
				
				}

				// get the modtables for each subblock
				modtable1 = (blockTop >> 29) & 0x7;
				modtable2 = (blockTop >> 26) & 0x7;



   
				if(!bFlip)/* 2*4 block */
				{



					for (int a = 0; a< 4; a++) // vertical
					{
						for (int b = 0; b < 2; b++) // horizontal
						{
							//*(output + j * x + k) =
						
			
						
					//
					piex[mark+  a*w+b]=(modifyPixel((int)red1, (int)green1, (int)blue1, b, a, blockBot, (int)modtable1));
							//*(output + j * x + k + 2) =
							
							piex[ mark+ a*w+b+2]=
					//	piex[mark+  a*w+b];
						(modifyPixel((int)red2, (int)green2,(int) blue2, b + 2, a, blockBot, (int)modtable2));

						//if(offset<120)
							//	System.out.println("no:"+piex[ mark+ a*w+b+2]);
							
						}
					}



				}
				else/*flip*/
				{

					for (int a = 0; a< 2; a++) // vertical
					{
						for (int b = 0; b < 4; b++) // horizontal
						{
							
							//*(output + j * x + k) =
							piex[ mark+ a*w+b]=(modifyPixel((int)red1, (int)green1, (int)blue1, b, a, blockBot, (int)modtable1));
							
		
							//*(output + j * x + k + 2) =
						piex[ mark+ (a+2)*w+b]=
						//	piex[ mark+ a*w+b];
						(modifyPixel((int)red2, (int)green2,(int) blue2, b ,a+2, blockBot, (int)modtable2));
//						
						if(offset<120)
//							
								System.out.println(  bDiff+    "_yes:"+ (int)red2+","+(int)green2+","+(int) blue2+","+b+" ,"+(a+2)  +":->"+piex[ mark+ (a+2)*w+b]);
//
						}
					}
				}



			}


		}

		
		return piex;


	}
	/*

	 Decompress to ARGB8888

	 */
	public static byte[] PVRTDecompressETC(PVRTHeader head) throws IOException
	{

		int[] pix = PVRTDecompressETC_int(head);

		ByteArrayOutputStream os = new ByteArrayOutputStream();

		MyDataOutPutStream myos = new MyDataOutPutStream(os);
		for(int p :pix)
			myos.writeInt(p);
		return  ((ByteArrayOutputStream) myos.getOuputStream()).toByteArray();

	}
	
	


	/* !***********************************************************************
	 @Function modifyPixel
	 @Input red Red value of pixel 
	 @Input green Green
	 value of pixel 
	 @Input blue Blue value of pixel
	 @Input x Pixel x position
	 in block @Input y Pixel y position in block
	 @Input modBlock Values for the 
	 current block 
	 @Input modTable Modulation value
	 s @Returns Returns actual
	 pixel colour
	 @Description Used by ETCTextureDecompress
	 ************************************************************************ */
	static int modifyPixel(int red, int green, int blue, int x, int y,
							long modBlock, int modTable) {
		int index = x * 4 + y, pixelMod;
		long mostSig = modBlock << 1;

		if (index < 8)
			pixelMod =
				mod[modTable][(int)(((modBlock >> (index + 24)) & 0x1) +
				((mostSig >> (index + 8)) & 0x2))];
		else
			pixelMod =
				mod[modTable][(int)(((modBlock >> (index + 8)) & 0x1) +
				((mostSig >> (index - 8)) & 0x2))];

		red = _CLAMP_(red + pixelMod, 0, 255);
		green = _CLAMP_(green + pixelMod, 0, 255);
		blue = _CLAMP_(blue + pixelMod, 0, 255);

		return ((red << 16) + (green << 8) + blue) | 0xff000000;
	}

	private static int _CLAMP_(int pixelMod, int p1, int p2)
	{
		return (pixelMod)<(p2)?  ((pixelMod)<(p1)?(p1):(pixelMod)  )  : (p2);
	}


}

 

从PowerSDK里修改成的java版,结合安卓的类可以显示pvr图片

    int[] data=PVRTDecompress.PVRTDecompressETC_int(he);
                Bitmap bmp=    Bitmap.createBitmap(data, he.width,he.heigth,Bitmap.Config.ARGB_8888);
                bmp.compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(outname_png));

 

posted on 2017-06-19 16:42  FormatFa  阅读(346)  评论(0编辑  收藏  举报