Free Image简单使用

FreeImage简介

FreeImage is an Open Source library project for developers who would like to support popular graphics image formats like PNG, BMP, JPEG, TIFF and others as needed by today‘s multimedia applications. FreeImage is easy to use, fast, multithreading safe, compatible with all 32-bit or 64-bit versions of Windows, and cross-platform (works both with Linux and Mac OS X).

简单地说就是一个跨平台的轻量图片库。貌似cocos2d用的图片加载的库就是这个。

源码下载 - FreeImage 3.16

编译

环境 - Windows 8.1

VS2008 (为了编译这个专门装的)

源码下载好,解压之后根目录下就有编译的工程文件,直接打开编译就好了。Debug和Release都编译一遍。

编译好之后就有FreeImage.dll, FreeImage.lib, FreeImaged.dll, FreeImaged.lb.

接下来编译C++ 的Wraper。

打开这个工程,X:\FreeImageSource\Wrapper\FreeImagePlus\FreeImagePlus.2008.sln

和刚才一样,Debug和Release都编译一遍。

接下来编译C++ Wraper的 测试工程

X:\FreeImageSource\Wrapper\FreeImagePlus\test\fipTest.2008.sln

将最外面的test.jpg拷贝到运行目录,挨个执行四个测试。

可能遇到的问题

找不到头文件

在这里添加头文件的目录

找不到lib

在下面的位置添加

这不到dll

将对应的dll拷贝到程序运行目录

测试程序崩溃

将test.jpg拷贝到运行目录。

简单使用

创建一个工程,还有要用到一张图片。

(Please call me LeiFeng.)

首先来最简单的,加载一张JPEG图片

#include "stdafx.h"
#include <iostream>
#include "FreeImagePlus.h"

int _tmain(int argc, _TCHAR* argv[])
{
	FreeImage_Initialise(TRUE);
	FIBITMAP * JPEG = FreeImage_Load(FIF_JPEG, "test.jpg", JPEG_DEFAULT);
	//获取影像的宽高,都以像素为单位
	int Width = FreeImage_GetWidth(JPEG);
	int Height = FreeImage_GetHeight(JPEG);
	std::cout << "Width: " << Width <<  "\nHeight: "  <<Height << std::endl;
	FreeImage_Unload(JPEG);
	FreeImage_DeInitialise();
	return 0;
}

颜色调整

常见的图片颜色调整FreeImage都已经实现,调用对应的接口就可以了。这里调用一个反色,还有一个调整曲线。

(容我先擦一下鼻血)

代码

FreeImage_AdjustContrast(JPEG, 15.0);
FreeImage_AdjustBrightness(JPEG, 50.0);

//FreeImage_Invert(JPEG);
if (JPEG)
{
	FreeImage_Save(FIF_BMP, JPEG, "test.bmp", BMP_DEFAULT);
}

gif的拷贝

从一张gif生成一张一模一样的gif

	BOOL bMemoryCache = TRUE;

	fipMultiPage src(bMemoryCache);
	fipMultiPage dst(bMemoryCache);

	// You MUST declare this before using it.
	// We will use the assignement operator, i.e. operator=()
	fipImage image;

	// Open src file (read-only, use memory cache)
	src.open("example.gif", FALSE, TRUE);

	if (src.isValid()) {
		// Open dst file (creation, use memory cache)
		dst.open("output.gif", TRUE, FALSE);

		// Get src page count
		int count = src.getPageCount();

		// Clone src to dst
		for (int page = 0; page < count; page++) {
			// Load the bitmap at position ‘page‘
			image = src.lockPage(page);
			if (image.isValid()) {
				// add a new bitmap to dst
				dst.appendPage(image);
				// Unload the bitmap (do not apply any change to src)
				src.unlockPage(image, FALSE);
			}
		}
	}
	std::cout << FreeImage_GetPageCount(dst) << std::endl;
		// Close src
		src.close(0);
		// Save and close dst
		dst.close();

查看gif的metadate

	fipMultiPage src(bMemoryCache);

	src.open("example.gif", FALSE, TRUE);
	fipImage image;
	image = src.lockPage(0);
	fipMetadataFind finder;
	if (finder.findFirstMetadata(FIMD_ANIMATION, image, tagg)) {
		do {
			// process the tag
			const void * p = tagg.getValue();
			DWORD* pp = (DWORD *)p;
			cout << "process the tag :" << tagg.getKey() << " " <<tagg.getType()<< " " << *pp << endl;
			tagVector.push_back(tagg);
		} while (finder.findNextMetadata(tagg));
	}

最后用完记得unlockPage.

随便加载一个gif,得到对用的tag有下面这些

其中最重要的是FrameTime,表示帧占用的时间,单位是毫秒。其次是Loop,是一只循环播放(0)还是循环一次(1),

从静态图片生成gif

先下载几个png

这个问题卡了我将近一天,文档上全是坑。

先上文档中专门说gif生成的代码

// assume we have an array of dibs which are already 8bpp and all the same size,
// and some float called fps for frames per second
FIMULTIBITMAP *multi = FreeImage_OpenMultiBitmap(FIF_GIF, "output.gif", TRUE, FALSE);
DWORD dwFrameTime = (DWORD)((1000.0f / fps) + 0.5f);
for(int i = 0; i < 10; i++ ) {
// clear any animation metadata used by this dib as we’ll adding our own ones
FreeImage_SetMetadata(FIMD_ANIMATION, dib[i], NULL, NULL);
// add animation tags to dib[i]
FITAG *tag = FreeImage_CreateTag();
if(tag) {
FreeImage_SetTagKey(tag, "FrameTime");
FreeImage_SetTagType(tag, FIDT_LONG);
FreeImage_SetTagCount(tag, 1);
FreeImage_SetTagLength(tag, 4);
FreeImage_SetTagValue(tag, &dwFrameTime);
FreeImage_SetMetadata(FIMD_ANIMATION, dib[i], FreeImage_GetTagKey(tag), tag);
FreeImage_DeleteTag(tag);
}
FreeImage_AppendPage(multi, dib[i]);
}
FreeImage_CloseMultiBitmap(multi);

似乎先创建一个multiBitmap,然后各种appendPage就可以了。

Too Young.

先看一下gif的文件格式

GIF格式,是为使图片能够应用在在线(online)应用程序上所特别开发的图片格式。Gif,有时也被成为“Giff”,是一种无损,8位图片格式。“无损”是指100%的保持原始图片的像素数据信息。专业名词“8位”是指,所能表现的颜色深度——一个8位图像仅最多只能支持256种不同颜色(一个多余256种颜色的图片若用gif图片保存会出现失真)。

So,上面的那个png是32bit的,不是8位的图片是Append不上的,那就转格式呗。

自带一个convertTo8Bits的方法,但是转换出来是灰度的。

上论坛搜索答案,告知就是这样的。

要用一个colorQuantize方法,结果完全无效,上论然搜,告知要24位的图片才能转。

继续转呗,透明的部分全部变黑。

论坛上搜索无果,回头继续看png的格式

PNG图片类型
PNG格式有8位、24位、32位三种,下面是一些术语:

索引透明:类似于GIF,某一像素只有全透和全不透明两种效果
Alpha透明:半透明
PNG8 - 8位的PNG最多支持256(2的8次方)种颜色,8位的PNG支持索引透明和alpha透明。
PNG24 - 支持2的24次方种颜色,但不支持透明信息。
PNG32 - 32位的PNG在24位的PNG基础上增加了8位的透明信息,因此支持不同程度的半透效果。

默默地打开屁艾斯(PS),加载图片,存储为Web所用格式。

重新用代码记载,appendpage,全世界都安静了。

代码清单(用的plus的wraper)

#include "stdafx.h"
#include <iostream>
#include "FreeImagePlus.h"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{

	BOOL bMemoryCache = TRUE;

	fipMultiPage dst(bMemoryCache);

	fipImage image1;
	image1.load("11.png");
	fipImage image2;
	image2.load("2.png");
	fipImage image3;
	image3.load("3.png");

	image2.convertTo24Bits();
	image2.colorQuantize(FIQ_WUQUANT);
	image3.convertTo24Bits();
	image3.colorQuantize(FIQ_WUQUANT);

	float fps = 3.0f;
	DWORD dwFrameTime = (DWORD)((1000.0f / fps) + 0.5f);
	fipTag tag;
	tag.setKey("FrameTime");
	tag.setType(FIDT_LONG);
	tag.setCount(1);
	tag.setLength(4);
	tag.setValue(&dwFrameTime);
	const void * p = tag.getValue();
	DWORD* pp = (DWORD *)p;
	cout << "Tag" << tag.getKey() << " " << *pp << endl;

	//Set the loop of gif 0->loop forever 1->loop only once.
	DWORD bloop = (DWORD)(1);
	fipTag loopTag;
	loopTag.setKey("Loop");
	loopTag.setType(FIDT_LONG);
	loopTag.setCount(1);
	loopTag.setLength(4);
	loopTag.setValue(&bloop);

	image1.setMetadata(FIMD_ANIMATION, tag.getKey(), tag);
	image2.setMetadata(FIMD_ANIMATION, tag.getKey(), tag);
	image3.setMetadata(FIMD_ANIMATION, tag.getKey(), tag);

	image1.setMetadata(FIMD_ANIMATION, loopTag.getKey(), loopTag);
	image2.setMetadata(FIMD_ANIMATION, loopTag.getKey(), loopTag);
	image3.setMetadata(FIMD_ANIMATION, loopTag.getKey(), loopTag);

	dst.open("output.gif", TRUE, FALSE);

	dst.appendPage(image1);
	dst.appendPage(image2);
	dst.appendPage(image3);

	dst.close(); return 0;
}

最终效果,guang~

第一张png是由ps导出的8位png,后面的两张用代码转的8位。

时间: 2024-10-13 03:20:38

Free Image简单使用的相关文章

C# Ping 简单使用

编程过程中,有时候需要判断主机是否在线,最简单的方法就是使用Windows的Ping命令看看能否ping通.看到网上很多文章,说用C#去调用windows的ping.exe,然后解析返回的字符串.我觉得这种方式太麻烦了,就做一下简单判断,不想弄那么麻烦. 查了一下,C#专门提供了一个Ping类,与Windows下的ping命令类似: 命令空间: System.Net.NetworkInformation; 使用方法: bool online = false; //是否在线 Ping ping =

自动生成简单四则运算的C语言程序

该程序是在博客园里面找的,具体是谁的找了半天没找到,无法提供它原本的链接.由于自己写的过于简单,且有一些功能暂时无法实现,所以就找了一个来应付作业,望原谅.在这个程序的源码中我改了一个错误的地方,源码中有这样一个随机数发生器的初始化函数的语句:"srand((unsigned)time(NULL))".srand函数是随机数发生器的初始化函数.但是正确的写法应该是:srand(unsigned( time(NULL))):为了防止随机数每次重复,常常使用系统时间来初始化,即使用time

Mysql的锁机制与PHP文件锁处理高并发简单思路

以购买商品举例: ① 从数据库获取库存的数量. ② 检查一下库存的数量是否充足. ③ 库存的数量减去买家购买的数量(以每个用户购买一个为例). ④ 最后完成购买. 仅仅这几行逻辑代码在并发的情况下会出现问题,自己可以想象一下. 这里暂时就不测试了,下面会针对并发的处理给出测试结果. 创建表: CREATE TABLE `warehouse` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `stock` int(11) NOT NULL

Winfrom 简单的安卓手机屏幕获取和安卓简单操作

为啥我要做这个东西了,是因为经常要用投影演示app ,现在有很多这样的软件可以把手机界面投到电脑上 ,但都要安装,比如说360的手机助手,我又讨厌安装,于是就自己捣鼓了下 做了这个东西, 实现了以下简单功能   1.屏幕获取(因为是截图方式获取的,所以有点卡顿) 2.实现点击功能,并在点击的时候出现一个手势图标,方便用户观看 3.实现简单的滑动功能 4.实现在界面上画图功能 5.实现拖拽安装apk功能 操作说明:鼠标左边 模拟手机点击,中键停止/开始刷新界面(画图的时候不能刷新),右键去掉画图内

iOS instruments之ui automation的简单使用(高手绕道)

最近使用了几次instruments中的automation工具,现记录下automation的简单使用方法,希望对没接触过自动化测试又有需求的人有所帮助.  UI 自动测试是iOS 中重要的附加功能,它由名为"Automation"的新的工具对象支持.Automation工具的脚本是用JavaScript语言编写,主要用于分析应用的性能和用户行为,模仿/击发被请求的事件,利用它可以完成对被测应用的简单的UI测试及相关功能测试. 一. 简单的录制脚本 打开xcode,这里用我为我家亲爱

Android ExpandableListView 带有Checkbox的简单应用

expandablelistview2_groups.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height=&qu

Android ExpandableListView的简单应用

Expandablelistview1Activity.java package com.wangzhu.demoexpandablelistview; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.widg

一个简单的主机管理模拟程序

最近写的一个小练习,主要是把前面学的东西整合一下.写了一个简单的主机管理界面,主要是练习以下知识点: Session和Cookie进行登录验证(装饰器) 数据库的基本操作 (单表,1对多,多对多) Form的简单使用实现验证 Bootstrap模板写个简单界面 自定义分页 信号,中间件,CSRF,模板语言,JavaScript,AJAX等等 界面比较low,毕竟不是专业的. 附件里面是Django的源代码,3个文件放在一起winrar解压就可以打开

简单介绍一下vue2.0

Vue Vue是用于构建用户界面的渐进框架.作者尤雨熙特别强调它与其他的框架不同,Vue是渐进式的框架,可以逐步采用,不必一下就通过框架去重构项目. 另外Vue的核心库只专注于视图层,这样就更容易与其他库或现有项目进行集成,也更灵活. Vue在兼容性上不支持IE8以下版本的浏览器,用到了ECMAScript 5的功能,所有支持ECMAScript 5的浏览器都没问题,像这些: 安装 如果你已经熟悉并安装webpack那可以直接装一个CLI版即命令行工具,快速方便. $ npm install -

简单利用filetype进行文件上传

对于文件上传大家都很熟悉了,毕竟文件上传是获取webshell的一个重要方式之一,理论性的东西参考我的另一篇汇总文章<浅谈文件解析及上传漏洞>,这里主要是实战补充一下理论内容--filetype漏洞! filetype漏洞主要是针对content-type字段,主要有两种利用方式:    1.先上传一个图片,然后将content-type:image/jpeg改为content-type:text/asp,然后对filename进行00截断,将图片内容替换为一句话木马. 2.直接使用burp抓