Hadoop HIPI

Hadoop HIPI是一个用于分布式计算环境的图片处理框架,它提供了API来处理大文件,尤其是合并和分割图片。HIPI通过将小图片合并成大文件上传到Hadoop HDFS,解决了小文件性能问题。文章介绍了HIPI的用途、下载地址,并给出了上传和下载图片到Hadoop系统的示例代码。

Hadoop HIPI学习

1.Hipi是什么?

HIPI是hadoop图片处理的框架,它提供了用于在分布式计算环境中执行图片处理任务的API。

描述图如下:

 

2.HIPI作用:

用于合并小的图像文件,及切割算法。

3.为什么用要用HIPI框架

因为hadoop框架很适合大文件的操作,而我们平时使用的图片的文件都比较小,如果这种小文件不经过处理直接上传,会十分影响性能,所以HIPI框架具备图片的合并以及分割,Hadoop HIPI学习

2.Hipi是什么?

HIPI是hadoop图片处理的框架,它提供了用于在分布式计算环境中执行图片处理任务的API。

描述图如下:

 

本人的个人理解:

通过HIBI框架把客户端上传的多张图片合并成一个大的HIB文件,然后把这些大的文件上传到hadoop hdfs中,

(待续.。。。。)

3.HIPI作用:

用于合并小的图像文件,及切割算法。

帮我们很好的解决了这方面的问题.

4.HIPI官网: 官网中有很多有用的资料,大家可以看看

http://hipi.cs.virginia.edu/index.html

5.HIPI框架下载地址:

http://hipi.cs.virginia.edu/downloads.html

里面有几个版本,大家把HIPI开发版下载下来就可以了,里面的内容很全.

hipi-dev.tar.gz ---该版本为开发版

6.把本地的图片文件通过HIPI框架上传到hadoop系统中

(1).把hipi-dev.tar.gz中src的源码引入到eclipse的jar项目中.----之所以引入源码,因为目前HIPI还是有一些BUG的(不过对我们使用HIPI的影响不是很大)

例如:获取一个分辨率很大的图片,会报内存异常错误,导入源码后,可以对一些bug进行修改,或对现已有的功能进行定制化修改。

(2).把hipi-dev.tar.gz中3rdparty中的metadata-extractor-2.3.1.jar和junit-4.11.jar,导入的到项目中去.否则会报错.

(3)上传代码:

往hib中添加1张图片,上传到hdfs中

/**

 * 

 */

package com.hd.hdfs;

 

import hipi.image.FloatImage;

import hipi.image.ImageHeader;

import hipi.image.ImageHeader.ImageType;

import hipi.imagebundle.AbstractImageBundle;

import hipi.imagebundle.HipiImageBundle;

 

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.util.ArrayList;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.Path;

 

/**

 * @author 

 *时间: @2013-12-18 @下午5:22:44

 *说明:上传数据

 * 

 */

public class UploadImage {

/**

 * 上传

 * @throws IOException

 */

public void myUploadImage() throws IOException{

//ArrayList<String> hosts=new ArrayList<String>();

Configuration conf=new Configuration();

conf.addResource(new Path("d:\\core-site.xml"));

conf.addResource(new Path("d:\\hdfs-site.xml"));

 

conf.addResource(new Path("d:\\mapred-site.xml"));

HipiImageBundle hib=new HipiImageBundle(new Path("/test/file2.hib"), conf);

hib.open(AbstractImageBundle.FILE_MODE_WRITE,true);

File file=new File("c:\\a.jpg");

FileInputStream fis=new FileInputStream(file);

hib.addImage(new FileInputStream(new File("d:\\zc\\IMG_0325.jpg")),ImageType.JPEG_IMAGE);

hib.addImage(fis,ImageType.JPEG_IMAGE);

hib.close();

}

 

/**

 * 追加数据

 * @param args

 * @throws IOException 

 * 把file2中的数据追加到file3中

 */

public void addpendImage() throws IOException{

Configuration conf=new Configuration();

conf.addResource(new Path("d:\\core-site.xml"));

conf.addResource(new Path("d:\\hdfs-site.xml"));

 

conf.addResource(new Path("d:\\mapred-site.xml"));

HipiImageBundle hib=new HipiImageBundle(new Path("/test/file3.hib"), conf);

hib.open(AbstractImageBundle.FILE_MODE_WRITE,true);

File file=new File("d:\\zc\\IMG_0321.jpg");

FileInputStream fis=new FileInputStream(file);

hib.addImage(fis,ImageType.JPEG_IMAGE);

HipiImageBundle hib1=new HipiImageBundle(new Path("/test/file2.hib"), conf);

hib.append(hib1);

}

 

public static void main(String[] args) {

try {

new UploadImage().myUploadImage();

//new UploadImage().addpendImage();

//new UploadImage().addInfo();

} catch (IOException e) {

e.printStackTrace();

}

}

}

 

4.从hdfs 中读取图片数据,然后保存到本地

/**

 * 

 */

package com.hd.hdfs;

 

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

 

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.Path;

 

 

import hipi.image.FloatImage;

import hipi.image.ImageHeader;

import hipi.image.io.JPEGImageUtil;

import hipi.imagebundle.AbstractImageBundle;

import hipi.imagebundle.HipiImageBundle;

 

/**

 * @author 

 *时间: @2013-12-19 @上午11:54:28

 *说明:hdfs中读取HIB数据,保存到本地中

 * 

 */

public class DonloadInfo extends HipiImageBundle {

 

/**

 * @param file_path

 * @param conf

 */

public DonloadInfo(Path file_path, Configuration conf) {

super(file_path, conf);

 

try {

//开启模式

this.openForRead();

 while (this.hasNext()) {

  ImageHeader imageHeader = this.next();

FloatImage image = this.readImage();

JPEGImageUtil.getInstance().encodeImage(image, imageHeader, new FileOutputStream(new File("c:\\b.jpg")));

  }

 this.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public static void main(String[] args) {

Configuration conf=new Configuration();

conf.addResource(new Path("d:\\core-site.xml"));

conf.addResource(new Path("d:\\hdfs-site.xml"));

 

conf.addResource(new Path("d:\\mapred-site.xml"));

new DonloadInfo(new Path("hdfs://192.168.1.200:9000/test/file2.hib"),conf);

}

 

}

 

上面代码就是读区图片信息,如果大家在试验中上传的分别率过大图片在读取的时候,会报内存溢出,这是由于HIBI源码的一个bug.(如果上传一个较小分别率图片的话是没有问题的)

 

分析BUG原因:

进入HipiImageBundle中会发现.

代码225行报错:

Image=decoder.decodeImage(_byte_arrayinput_stream);

_byte_array_input_stream输入流是中是获取的到是正确的.主要是decodeImage接口代码中有问题

,进入实现类JPEGImageUtil类中,找到decodeImage()方法,在代码98行中发现,

float[] pels new float[w*h*3];

W和h代表图片的分辨率,如果你的分辨率过大的话,会出现w*h*3超过了float数组的返回,就会报内存溢出错误.

 

解决办法:

在源码包中HIpiIImageBundle中,添加如下方法:

private ByteArrayInputStream in=null;

public ByteArrayInputStream getByteArrayInputStream(){

if (in != null)

return in;

if (_cacheLength > 0) {

ImageDecoder decoder = CodecManager.getDecoder(ImageType

.fromValue(_cacheType));

if (decoder == null)

return null;

ByteArrayInputStream _byte_array_input_stream = new ByteArrayInputStream(_byte_array_data);

return_byte_array_input_stream;

}

return null;

}

 

 

 

然后在HipiImageBundle中的readImage()方法下面加入如下方法:

 

Public ByteArrayInputStream readByteArrayInputStream(){

return _reader.getByteArrayInputStream();

}

 

//现在我们就可以直接获取到ByteArrayInputStream流了, 该流就是每张图片的流,得到流后,就可以信息各种操作了.

源码修改后的,获取图片的代码:

/**

 * 

 */

package com.hd.hdfs;

 

import java.awt.image.BufferedImage;

import java.io.ByteArrayInputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

 

import javax.imageio.ImageIO;

 

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.Path;

 

import com.sun.image.codec.jpeg.JPEGCodec;

import com.sun.image.codec.jpeg.JPEGEncodeParam;

import com.sun.image.codec.jpeg.JPEGImageEncoder;

 

 

import hipi.image.FloatImage;

import hipi.image.ImageHeader;

import hipi.image.io.JPEGImageUtil;

import hipi.imagebundle.AbstractImageBundle;

import hipi.imagebundle.HipiImageBundle;

 

/**

 * @author 

 *时间: @2013-12-19 @上午11:54:28

 *说明:hdfs中读取HIB数据,保存到本地中

 * 

 */

public class DonloadInfo extends HipiImageBundle {

 

/**

 * @param file_path

 * @param conf

 */

public DonloadInfo(Path file_path, Configuration conf) {

super(file_path, conf);

 

try {

//开启模式

this.openForRead();

ByteArrayInputStream by=null;

BufferedImage bufferedImage=null;

int len=0;

byte b[]=new byte[1024];

int i=0;

 while (this.hasNext()) {

  ImageHeader imageHeader = this.next();

  by=this.readByteArrayInputStream();

  i++;

  FileOutputStream out=new FileOutputStream("c:\\img\\a"+i+".jpg");

  while((len=by.read(b))!=-1){

  out.write(b, 0, len);

  }

  out.close();

  

  }

 this.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public static void main(String[] args) {

Configuration conf=new Configuration();

conf.addResource(new Path("d:\\core-site.xml"));

conf.addResource(new Path("d:\\hdfs-site.xml"));

 

conf.addResource(new Path("d:\\mapred-site.xml"));

new DonloadInfo(new Path("hdfs://192.168.1.200:9000/test/file2.hib"),conf);

}

 

}


 

 

 

 


 

评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值