在 Android 上获取 TIFF 图像的单像素
Posted
技术标签:
【中文标题】在 Android 上获取 TIFF 图像的单像素【英文标题】:Get single pixel of TIFF image on Android 【发布时间】:2017-09-16 05:01:07 【问题描述】:理想情况下,我需要在我正在开发的 android 应用上离线访问墨西哥地形的高度信息。我下载了一个 .bil 文件并用 QGIS 将其转换为一个 .tif 文件,生成的文件将近 900 MB。
我不知道它是否可行,我仍在学习开发 Android 应用程序,但我计划将其存储在 SD 卡中,我想知道是否可以访问单个像素而无需阅读整个图像,因为我知道这是不可能的。
谁能告诉我这是否可能?如果是,该怎么做?或者以任何其他方式获取我需要的信息,可能会将 .bil 文件转换为其他格式或类似的格式。
感谢您的回答。
【问题讨论】:
我无法回答部分 .tif 读数,但一种有效的替代方法是构建一个包含图像的所有 x/y/color 值的数据库创建脚本,然后简单地与之交互当您需要正确的颜色时使用数据库。 【参考方案1】:Tiff 将图像存储为从定义的偏移量开始的字节行。因此,您可以轻松检索单个像素,当然无需加载完整图像。 如果您在十六进制编辑器中打开任何 tif 文件,您将看到前 4 个字节通过代码标记 tiff。接下来的 4 个字节为关于 tif 图像的元数据提供偏移量。 使用随机访问文件打开图像 tif 文件,然后寻找偏移量并进入元数据空间。从这里您可以选择所需像素的偏移量。那就去拿吧..
我们有 tiff 仅用于此目的。那就是访问单个像素。如果我们需要完全加载图像,那么 jpeg 或 BMP 就足够了。
【讨论】:
【参考方案2】:查看此链接以获取完整代码:- full example to decode tiff image
package com.tif;
import android.os.*;import android.content.*;import android.app.*;import android.widget.*;import android.view.*;
import android.view.View.*;import android.graphics.*;import java.io.*;import java.util.*;import android.util.*;
import java.lang.*;import java.nio.*;import java.nio.channels.*;
public class Main extends Activity
private static final int CLEAR_CODE = 256;
private static final int EOI_CODE = 257;
long bytesCount=0L;
ScrollView sv;TextView tv;ImageView iv;
List intList;
long[] stripOffs,stripBytes;
byte[] bytes,ubytes,bmpBytes;
ByteBuffer bBuff;
BitBuffer bitBuff;
int entries,type,tag;
long count,value,ifd,stripAt,stripCount,stripBytesAt,rows,cols;
String txt="Null",path="",decompressed="";
String[] info= "width","length","bitsPerSample","Compression","PhotometricInterpretation","FillOrder","StripOffsets","SamplesPerPixel","RowsPerStrip"
,"StripBytes","XResolution","YResolution","PlanarConfig","ResolutionUnit","extra","NextIFD";
Bitmap bmp=null;
class DotsView extends View
int i = 0;Bitmap bmp;Canvas cnv;Rect bounds;Paint p;int width,height;
int alfa,red,green,blue;
public DotsView(Context context ,int width ,int height)
super(context);
this.width = width;
this.height = height;
bmp = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
cnv = new Canvas(bmp);
bounds = new Rect(0 , 0, width,height);
p = new Paint();
@Override
protected void onDraw(Canvas c)
for(int i=0;i<width;i++)
for(int j=0;j<height;j++)
for(int pix=0;pix<3;pix++)
if(pix==0)blue=bmpBytes[i+j+pix];
if(pix==1)green=bmpBytes[i+j+pix];
if(pix==2)red=bmpBytes[i+j+pix];
p.setColor( Color.argb(255, red,green,blue) );
cnv.drawPoint(i,j, p);
c.drawBitmap(bmp, null, bounds , null);
invalidate();
public int myShort(short sh)
int i;
ByteBuffer shortBuff=ByteBuffer.allocate(4);
shortBuff.order(ByteOrder.BIG_ENDIAN);shortBuff.putShort(sh);shortBuff.rewind();
shortBuff.order(ByteOrder.LITTLE_ENDIAN);sh=shortBuff.getShort();
if(sh<0)i=(int)(sh+32768); else i=(int)sh;
return i;
public long myInt(int i)
long l=0L;
ByteBuffer intBuff=ByteBuffer.allocate(4);
intBuff.order(ByteOrder.BIG_ENDIAN);intBuff.putInt(i);intBuff.rewind();
intBuff.order(ByteOrder.LITTLE_ENDIAN); i=intBuff.getInt();
if(i<0)l=(long)(i+2147483648L); else l=(long)i;
return l;
public String tagInfo(int tag)
int i=0;
switch(tag)
case 256: i=0;break;case 257: i=1;break;case 258: i=2;break;case 259: i=3;break;case 262: i=4;break;case 266: i=5;break;
case 273: i=6;break;case 277: i=7;break;case 278: i=8;break;case 279: i=9;break;case 282: i=10;break;case 283: i=11;break;
case 284: i=12;break;case 296: i=13;break;case 1496: i=14;break;case 0: i=15;break;
return info[i];
public void extractTif()
String taginfo="";String strVal="";
FileInputStream fis;BufferedInputStream bis;DataInputStream dis;
path=Environment.getExternalStorageDirectory().getPath();
path=path+"/DCIM"+"/kpd.tif";
try
fis=new FileInputStream(path);bis=new BufferedInputStream(fis);dis=new DataInputStream(bis);
dis.skip(4);ifd=myInt(dis.readInt());
txt="TIFF-IFD: "; txt=txt+ifd;
dis.skip(ifd-8); entries=myShort(dis.readShort());
txt=txt+"\nNo.OfEntries="+entries;
for(int i=0;i<=entries;i++)
tag=myShort( dis.readShort() );taginfo=tagInfo(tag);
type=myShort( dis.readShort() );count=myInt( dis.readInt() );value=myInt( dis.readInt() );
if(type==3)strVal="Value="; else strVal="Offset=";
if( strVal.equals("Offset=") )
if( taginfo.equals("StripOffsets") )stripAt=value;stripCount=count;
if( taginfo.equals("StripBytes") )stripBytesAt=value;
if( taginfo.equals("width") )cols=value;
if( taginfo.equals("length") )rows=value;
txt=txt+"\ntag="+tag+" "+tagInfo(tag)+",type="+type+",count="+count+strVal+value;
dis.close();bis.close();fis.close();
catch(Exception e) txt=txt+"\nerror="+e.toString();
txt=txt+"\nNo.OfStrips="+stripCount+",array of strip locations at: "+stripAt+" and array of bytesPerStrip at "+stripBytesAt ;
extractBMP();
public void extractBMP()
try File f=new File(path);RandomAccessFile raf=new RandomAccessFile(f,"r");
raf.seek(stripAt);stripOffs=new long[(int)stripCount];
txt=txt+"\nArray Of Image Offsets=";
for(int i=0;i<stripCount;i++)stripOffs[i]=myInt( raf.readInt() ); txt=txt+","+stripOffs[i];
raf.seek(stripBytesAt); stripBytes=new long[(int)stripCount];
txt=txt+"\nArray Of Strip Bytes =";
for(int i=0;i<stripCount;i++)stripBytes[i]=myInt(raf.readInt()); txt=txt+","+stripBytes[i];bytesCount+=stripBytes[i];
txt=txt+stripBytes;
bBuff =ByteBuffer.allocate((int)(rows*cols*3));
for(int i=0;i<stripCount;i++)
bytes =new byte[(int)stripBytes[i]];
raf.seek(stripOffs[i]);
raf.read(bytes);
bBuff.put(lzwUncompress(bytes));
bytes=null;
txt=txt+"\nBuffered Image Bytes Size="+bBuff.position();
bBuff.rewind();
bmpBytes=new byte[bBuff.remaining()];
bmpBytes=bBuff.array();
txt=txt+"\nCount of bmpBytes="+bmpBytes.length;
bmp=BitmapFactory.decodeByteArray(bmpBytes,0,bmpBytes.length);
SystemClock.sleep(5000);
txt=txt+"Bitmap Object, bmp="+bmp;
if(bmp!=null)iv.setImageBitmap(bmp);sv.addView(iv);
raf.close();
catch(Exception e)txt=txt+"\nerror="+e.toString();
public void lzw()
//String[] table=new String[4096];
byte b;char ch;String s;String pre="";short sh;
//List strTable=Arrays.asList(table);
//for(int i=0;i<255;i++)table[i]=Character.toString((char)i);
for(int i=0;i<100;i++)
b=bytes[i];
if(b<0)sh=(short)(128+b);
else sh=(short)b;
//ch=(char)b;
s=String.valueOf(sh);
//s=s+pre;
//if(strTable.contains(s))pre=s;
//else
txt=txt+"Byte No."+i+"="+s+" ";
public void onCreate(Bundle bnd)
super.onCreate(bnd);
extractTif();
//sv=new ScrollView(this);
//tv=new TextView(this);
//iv=new ImageView(this);
//tv.setTextSize(7);
//sv.addView(tv);
//sv.addView(iv);
//tv.setText(txt);
//setContentView(sv);
Point res=new Point(); getWindowManager().getDefaultDisplay().getSize(res);
DotsView myView = new DotsView(this,res.x,res.y);
setContentView(myView);
【讨论】:
以上是关于在 Android 上获取 TIFF 图像的单像素的主要内容,如果未能解决你的问题,请参考以下文章
如何为使用 python 保存的 tiff 图像设置像素大小,以便将像素高度和宽度设置为 ImageJ 中的特定值?