请问大虾们,如何用C++得到缩略图啊,高压缩比的

Rossoneri 2011-04-19 06:41:35
我用imagemagick里面的zoom()函数转换一个60多兆的相机图片(4288*2848),得到200*133的147K,1024*680的3.61M,虽然很小了,可是跟预期还是有很大差距啊,像windows上显示的缩略图肯定很小的,用C++有没有更好的方法,多谢。
...全文
541 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Rossoneri 2011-04-20
  • 打赏
  • 举报
回复
LS的需要自己写算法啊,有没有现成的函数啊
我又试了下,发现是图片里面包含了很多exif信息,什么模式了,曝光了之类的无用信息,要是能把这些信息去掉就好了,有没有知道的兄弟姐妹们啊,拜托啊
方紫涵 2011-04-20
  • 打赏
  • 举报
回复
up 玄机
pathuang68 2011-04-20
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 rocco22 的回复:]

LS的需要自己写算法啊,有没有现成的函数啊
我又试了下,发现是图片里面包含了很多exif信息,什么模式了,曝光了之类的无用信息,要是能把这些信息去掉就好了,有没有知道的兄弟姐妹们啊,拜托啊
[/Quote]

4L给的不就是函数么,还给出了main函数告诉你怎么用...当然图像像素的像素,你需要自己改动一下(用参数传入)这个不难吧?

bmp<->jpeg转换,可以用jpeglib。
Meteor_Code 2011-04-20
  • 打赏
  • 举报
回复
xinmage,帮你解决你的图片问题
请关注我的下载

http://download.csdn.net/source/1439447
xmu_才盛 2011-04-20
  • 打赏
  • 举报
回复
up 玄机,,, 原来是搞图像的啊,,,

楼主既然用c++,就别想让别人给你做事。。。。

就跟开跑车开车一样, 还想让别人给你挂挡。。

那就应该用自动挡的大众去。。。
pathuang68 2011-04-19
  • 打赏
  • 举报
回复
这是3楼说的原理的VC优化实现:

// imagetest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <assert.h>


//------------------------------------------------
class Rothstein
{
public:
Rothstein(int p, int q);
int operator[] (int i) { return myData[i]; }
void Permute();
void PrintData();

~Rothstein();


private:
char *myData;
int myP, myQ;
};

class RowRothstein280
{
public:
RowRothstein280(int largerSize, int bpp); //increment according to byte per pixel
int operator[] (int i) { return myData[i]; }
void PrintData();

private:
int myData[280];
};

class ColRothstein210
{
public:
ColRothstein210(int largerSize, int bpl); //increment according to byte perl line
int operator[] (int i) { return myData[i]; }
void PrintData();

private:
int myData[210];
};

Rothstein::Rothstein(int p, int q)
{
myP = p;
myQ = q;
myData = new char[p];

if (p <= q) {
memset(myData, 1, p);
return;
}

char *ptr = myData;
int diff = p - q;
int curr = q;
for (int i=0; i< p; i++) //if we want to permute the code, we need <<1
{
if(curr < p)
{
*ptr = 0;
curr += q;
}
else
{
*ptr = 1;
curr -= diff;
}
ptr++;
}
}

void Rothstein::Permute()
{
int temp = myData[0];

for (int i=0; i<myP-1; i++)
myData[i] = myData[i+1];

myData[myP-1] = temp;
}

void Rothstein::PrintData()
{

for (int i=0; i<myP; i++)
{
printf("%d\t", myData[i]);
}
printf("\n");
}

Rothstein::~Rothstein()
{
delete myData;
}

//Rothstein of size 280, for Row
// bpp = byte per pixel
RowRothstein280::RowRothstein280(int largerSize, int bpp)
{
// assert(largerSize > 280);

Rothstein rot(largerSize, 280);
int j = 0;
int oldData = 0;
for(int i = 0; i< largerSize; i++)
{
if (rot[i])
{
myData[j++]= (i - oldData)*bpp; //increment in bytes per pixel * number of pixels
oldData = i;
}
}
//printf("j is %d \n", j);

}

void RowRothstein280::PrintData()
{

for (int i=0; i<280; i++)
{
printf("%d\t", myData[i]);
}
// printf("\n");
}

ColRothstein210::ColRothstein210(int largerSize, int bpl)
{
// assert(largerSize > 210);

Rothstein rot(largerSize, 210);
int j = 0;
int oldData =0;
for(int i = 0; i< largerSize; i++)
{
if (rot[i])
{
myData[j++]= (i - oldData) * bpl; //increment by number of lines * bytes per line
oldData = i;
}
}
// printf("j is %d \n", j);

}

void ColRothstein210::PrintData()
{

for (int i=0; i<210; i++)
{
printf("%d\t", myData[i]);
}
printf("\n");
}

/*

HeavyRothstein

If we are shrinking an image from a columns to b columns, we are interested
in the Rothstein code for p = a, q = b.

If we are expanding an image from a columns to b columns, we are interested
in the Rothstein code for p = b, q = a.

HeavyRothstein takes two dimensions and automatically constructs a Rothstein
code with p set to the larger dimension and q set to the smaller dimension.

*/

//int minval(int a, int b) { return a < b ? a : b; }
//int maxval(int a, int b) { return a > b ? a : b; }

class HeavyRothstein : public Rothstein
{
public:
HeavyRothstein(int a, int b) : Rothstein(max(a, b), min(a, b)) {}
};


BYTE* bits = NULL;
BYTE* newbits = NULL;
FILE* file = NULL;
BITMAPFILEHEADER bf;
unsigned newwidth, newheight, newimagesize, newbfsize;
unsigned bmiSize;
unsigned imageSize;
int bpp, bpl;
RowRothstein280 *rot280;
ColRothstein210 *rot210;

void InitDevice()
{
//-------800x600 to 280x210
newwidth = 280;
newheight = 210;

//-------byte per pixel 3 original image byte per line 800 x 3 = 2400
bpp = 3;
bpl = 800*bpp; //2400

rot280 = new RowRothstein280(800, bpp);
rot210 = new ColRothstein210(600, bpl);

}



//from 800x600 to 280x210
void ResizeImage800to280(unsigned char* src, unsigned char* dst)
{
unsigned char* oldp; //pointer to the pix in the old image
int oldcol = 0;

for(int row = 0; row < 210; row++)
{
src += (*rot210)[row];
oldp = src;
for (int col = 0; col < 280; )
{ //unroll 10 times;
oldp += (*rot280)[col++];
memcpy(dst, oldp, bpp);
dst+=bpp;
oldp += (*rot280)[col++];
memcpy(dst, oldp, bpp);
dst+=bpp;
oldp += (*rot280)[col++];
memcpy(dst, oldp, bpp);
dst+=bpp;
oldp += (*rot280)[col++];
memcpy(dst, oldp, bpp);
dst+=bpp;
oldp += (*rot280)[col++];
memcpy(dst, oldp, bpp);
dst+=bpp;
oldp += (*rot280)[col++];
memcpy(dst, oldp, bpp);
dst+=bpp;
oldp += (*rot280)[col++];
memcpy(dst, oldp, bpp);
dst+=bpp;
oldp += (*rot280)[col++];
memcpy(dst, oldp, bpp);
dst+=bpp;
oldp += (*rot280)[col++];
memcpy(dst, oldp, bpp);
dst+=bpp;
oldp += (*rot280)[col++];
memcpy(dst, oldp, bpp);
dst+=bpp;
}
}
}

//-----------------------end 800x600 to 280x210 bpp=3--------------------------------------------------------



struct {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
} bmi;

void LoadBMP(char* filename)
{

if (!(file = fopen(filename, "rb"))) {
goto done;
}

if (fread(&bf, 1, sizeof(bf), file) != sizeof(bf)) {
goto done;
}

if (bf.bfType != *(WORD*) "BM") {
goto done;
}

bmiSize = bf.bfOffBits - sizeof(bf);
if (bmiSize > sizeof(bmi)) {
goto done;
}
if (fread(&bmi, 1, bmiSize, file) != bmiSize) {
goto done;
}
imageSize = (bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount / 8 + 3 & ~3) * bmi.bmiHeader.biHeight;
bits = new BYTE[imageSize];


if (fread(bits, 1, imageSize, file) != imageSize) {
goto done;
}

printf("image size is %d\n", imageSize);
printf("color is %d\n", bmi.bmiHeader.biBitCount);
printf("width is %d height is %d\n", bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight);

//image = LoadBMP((BITMAPINFO*) &bmi, bits);

done:
if (file) {
fclose(file);
}

}

// CopyPixel will copy a pixel

inline void CopyPixel(unsigned char *dst, unsigned char *src, int byteperpix)
{
for (int i=0; i<byteperpix; i++)
*dst++ = *src++;
}


//regular Rothstein algorithm
void ResizeImage(unsigned char* src, int sw, int sh, int sp, unsigned char* dst, int dw, int dh, int bpp)
{
unsigned char* oldp; //pointer to the pix in the old image
HeavyRothstein rothrow(dw, sw);
HeavyRothstein rothcol(dh, sh);
int oldcol = 0;

for (int col = 0; col < dh; col++)
{
// If shrinking in height, find a 1 in the Rothstein code
if (dh < sh) {
while (rothcol[oldcol] == 0) {
oldcol++;
src += sp;
}
}

// Resize a single row of the image.
oldp = src;

int oldrow = 0;

for(int row = 0; row < dw; row++)
{
// If shrinking in width, find a 1 in the Rothstein code
if (dw < sw) {
while (rothrow[oldrow] == 0) {
oldrow++;
oldp += bpp;
}
}

CopyPixel(dst, oldp, bpp);
dst += bpp;

// Advance the "old" pointer
// the # of cols specified in the Rothstein code
if (dw < sw) {
oldrow++;
oldp += bpp;
} else {
oldrow += rothrow[row];
oldp += rothrow[row] * bpp;
}
}

// Advance the "old" pointer the # of rows specified in the Rothstein code
if (dh < sh) {
oldcol++;
src += sp;
} else {
oldcol += rothcol[col];
src += sp * rothcol[col];
}
}
}

void ProcessBMP(char* filename)
{

// HeavyRothstein rotrow(bmi.bmiHeader.biWidth, newwidth);
// HeavyRothstein rotcol(bmi.bmiHeader.biHeight, newheight);

newimagesize = (newwidth* bmi.bmiHeader.biBitCount / 8 + 3 & ~3)* newheight;

newbits = new BYTE[newimagesize];

int bytes_per_line = bmi.bmiHeader.biBitCount / 8 * bmi.bmiHeader.biWidth + 3 & ~3;

// ResizeImage((unsigned char*) bits, bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight, bytes_per_line, (unsigned char*) newbits, newwidth, newheight, bmi.bmiHeader.biBitCount / 8);


ResizeImage800to280((unsigned char*) bits, (unsigned char*) newbits);

int filesize = sizeof(bf)+ bmiSize +newimagesize;
bf.bfSize = filesize;
bmi.bmiHeader.biWidth = newwidth;
bmi.bmiHeader.biHeight = newheight;
bmi.bmiHeader.biSizeImage = newimagesize;


if (!(file = fopen(filename, "wb"))) {
goto done;
}
if (fwrite(&bf, 1, sizeof(bf), file) != sizeof(bf)) {
goto done;
}

if (fwrite(&bmi, 1, bmiSize, file) != bmiSize) {
goto done;
}

if (fwrite(newbits, 1, newimagesize, file) != newimagesize) {
goto done;
}


done:
if (file) {
fclose(file);
}
if (bits) {
delete [] bits;
}
if (newbits) {
delete [] newbits;
}

if( rot280) {
delete rot280;
}
if( rot210) {
delete rot210;
}

}

int main(int argc, char* argv[])
{
char* infile;
char* outfile;

//if(argc > 2)
{
/*
infile = "test.bmp";
newwidth = 800;
newheight = 600;
outfile = "test1.bmp"; //argv[2];
*/
/*
infile = "wallpaper1.bmp"; //argv[1];
newwidth = 640;
newheight = 480;
outfile = "test.bmp"; //argv[2];
*/
infile = "test.bmp"; //argv[1];
outfile = "test2.bmp"; //argv[2];

InitDevice();

printf("in is %s\n", infile);
printf("out is %s\n", outfile);
LoadBMP(infile);
ProcessBMP(outfile);
}

// HeavyRothstein rot(800, 280);
// rot.PrintData();
// rot280.PrintData();
printf("Hello World!\n");
// rot210.PrintData();

// HeavyRothstein rot1(600, 210);
// rot1.PrintData();


return 0;
}
pathuang68 2011-04-19
  • 打赏
  • 举报
回复
俺在Berkley的网站,看到他们缩小图片的一种做法是这样的:

先把那个60M+的图片,转换成BMP(假定是12 x 12),没点24bits(RGB各一个byte):
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。
。 。 。 。 。 。 。 。 。 。 。 。

假定你要让它变成2 x 2的图像,你可以将上面的点阵分成2 x 2个 6 x 6的点阵。
针对每个6 x 6的点阵,把所有点的R、G、B的值加起来,分别得到sum_R、sum_G和sum_B,那么得到
点的颜色值就是(sum_R/36, sum_G/36, sum_B/36)

这样以来,36个点就缩小为一个点了。

完成后,再把这个缩小了的bmp转换为jpg就可以了。
Rossoneri 2011-04-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 wocaoqwer 的回复:]
再调用一次 不就更小了
[/Quote]
早试过了,不论用多少次,跟用一次一模一样,大小不会变
fight_flight 2011-04-19
  • 打赏
  • 举报
回复
再调用一次 不就更小了

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧