我使用下面的代碼來縮放jpeg,我從互聯網上的一個示例中獲得了ZoomOutJpeg()函數。調整jpeg圖像大小?
//JpegLib Error Handing - Begin
struct my_error_mgr
{
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
/*
* Here's the routine that will replace the standard error_exit method:
*/
METHODDEF(void)
my_error_exit(j_common_ptr cinfo)
{
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr)cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->output_message) (cinfo);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
//JpegLib Error Handing - End
/*
* zoom out picture. the factor should between 0.5 and 1.0. It can be 0.5, but can not be 1.0.
*/
bool ZoomOutJpeg(UINT8 *inBuff, UINT8 *outBuff, UINT32 inSize, UINT32* _outSize, float factor)
{
//if (factor > 1 || factor < 0.5f)
// return false;
// init decompress struct
struct jpeg_decompress_struct in;
JSAMPROW inRowPointer[1];
// init compress struct
struct jpeg_compress_struct out;
JSAMPROW outRowPointer[1];
struct my_error_mgr jerrIn;
struct my_error_mgr jerrOut;
/* We set up the normal JPEG error routines, then override error_exit. */
in.err = jpeg_std_error(&jerrIn.pub);
jerrIn.pub.error_exit = my_error_exit;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(jerrIn.setjmp_buffer))
{
jpeg_destroy_decompress(&in);
return false;
}
jpeg_create_decompress(&in);
jpeg_mem_src(&in, inBuff, inSize);
jpeg_read_header(&in, TRUE);
jpeg_start_decompress(&in);
out.err = jpeg_std_error(&jerrOut.pub);
jerrOut.pub.error_exit = my_error_exit;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(jerrOut.setjmp_buffer))
{
jpeg_destroy_decompress(&in);
jpeg_destroy_compress(&out);
return false;
}
jpeg_create_compress(&out);
jpeg_mem_dest(&out, &outBuff, (unsigned long*)_outSize);
int width = in.output_width;
int height = in.output_height;
int bytesPerPixel = in.num_components;
int destWidth = (int)(width * factor);
int destHeight = (int)(height * factor);
_outFrameSize->resX = destWidth;
_outFrameSize->resY = destHeight;
out.image_width = destWidth;
out.image_height = destHeight;
out.input_components = bytesPerPixel;
out.in_color_space = JCS_RGB;
jpeg_set_defaults(&out);
jpeg_start_compress(&out, TRUE);
// Process RGB data.
int outRowStride = destWidth * bytesPerPixel;
int inRowStride = width * bytesPerPixel;
outRowPointer[0] = (unsigned char *)malloc(outRowStride);
inRowPointer[0] = (unsigned char *)malloc(inRowStride);
JSAMPROW baseInRowPointer[1];
baseInRowPointer[0] = (unsigned char *)malloc(inRowStride);
unsigned char bUpLeft, bUpRight, bDownLeft, bDownRight;
unsigned char gUpLeft, gUpRight, gDownLeft, gDownRight;
unsigned char rUpLeft, rUpRight, rDownLeft, rDownRight;
unsigned char b, g, r;
float fX, fY;
int iX, iY;
int i, j;
int currentBaseLocation = -1;
int count = 0;
// Process the first line.
jpeg_read_scanlines(&in, inRowPointer, 1);
for (j = 0; j < destWidth; j++)
{
fX = ((float)j)/factor;
iX = (int)fX;
bUpLeft = inRowPointer[0][iX * 3 + 0];
bUpRight = inRowPointer[0][(iX + 1) * 3 + 0];
gUpLeft = inRowPointer[0][iX * 3 + 1];
gUpRight = inRowPointer[0][(iX + 1) * 3 + 1];
rUpLeft = inRowPointer[0][iX * 3 + 2];
rUpRight = inRowPointer[0][(iX + 1) * 3 + 2];
b = bUpLeft * (iX + 1 - fX) + bUpRight * (fX - iX);
g = gUpLeft * (iX + 1 - fX) + gUpRight * (fX - iX);
r = rUpLeft * (iX + 1 - fX) + rUpRight * (fX - iX);
outRowPointer[0][j * 3 + 0] = b;
outRowPointer[0][j * 3 + 1] = g;
outRowPointer[0][j * 3 + 2] = r;
}
jpeg_write_scanlines(&out, outRowPointer, 1);
currentBaseLocation = 0;
//Process the other lines between the first and last.
for (i = 1; i < destHeight - 1; i++)
{
fY = ((float)i)/factor;
iY = (int)fY;
if (iY == currentBaseLocation)
{
in.output_scanline = iY;
SwapJsampRow(inRowPointer[0], baseInRowPointer[0]);
jpeg_read_scanlines(&in, baseInRowPointer, 1);
}
else
{
in.output_scanline = iY - 1;
jpeg_read_scanlines(&in, inRowPointer, 1);
jpeg_read_scanlines(&in, baseInRowPointer, 1);
}
currentBaseLocation = iY + 1;
for (j = 0; j < destWidth; j++)
{
fX = ((float)j)/factor;
iX = (int)fX;
bUpLeft = inRowPointer[0][iX * 3 + 0];
bUpRight = inRowPointer[0][(iX + 1) * 3 + 0];
bDownLeft = baseInRowPointer[0][iX * 3 + 0];
bDownRight = baseInRowPointer[0][(iX + 1) * 3 + 0];
gUpLeft = inRowPointer[0][iX * 3 + 1];
gUpRight = inRowPointer[0][(iX + 1) * 3 + 1];
gDownLeft = baseInRowPointer[0][iX * 3 + 1];
gDownRight = baseInRowPointer[0][(iX + 1) * 3 + 1];
rUpLeft = inRowPointer[0][iX * 3 + 2];
rUpRight = inRowPointer[0][(iX + 1) * 3 + 2];
rDownLeft = baseInRowPointer[0][iX * 3 + 2];
rDownRight = baseInRowPointer[0][(iX + 1) * 3 + 2];
b = bUpLeft * (iX + 1 - fX) * (iY + 1 - fY) + bUpRight * (fX - iX) * (iY + 1 - fY) + bDownLeft * (iX + 1 - fX) * (fY - iY) + bDownRight * (fX - iX) * (fY - iY);
g = gUpLeft * (iX + 1 - fX) * (iY + 1 - fY) + gUpRight * (fX - iX) * (iY + 1 - fY) + gDownLeft * (iX + 1 - fX) * (fY - iY) + gDownRight * (fX - iX) * (fY - iY);
r = rUpLeft * (iX + 1 - fX) * (iY + 1 - fY) + rUpRight * (fX - iX) * (iY + 1 - fY) + rDownLeft * (iX + 1 - fX) * (fY - iY) + rDownRight * (fX - iX) * (fY - iY);
outRowPointer[0][j * 3 + 0] = b;
outRowPointer[0][j * 3 + 1] = g;
outRowPointer[0][j * 3 + 2] = r;
}
jpeg_write_scanlines(&out, outRowPointer, 1);
}
//Process the last line.
in.output_scanline = height - 1;
jpeg_read_scanlines(&in, inRowPointer, 1);
for (j = 0; j < destWidth; j++)
{
fX = ((float)j)/factor;
iX = (int)fX;
bUpLeft = inRowPointer[0][iX * 3 + 0];
bUpRight = inRowPointer[0][(iX + 1) * 3 + 0];
gUpLeft = inRowPointer[0][iX * 3 + 1];
gUpRight = inRowPointer[0][(iX + 1) * 3 + 1];
rUpLeft = inRowPointer[0][iX * 3 + 2];
rUpRight = inRowPointer[0][(iX + 1) * 3 + 2];
b = bUpLeft * (iX + 1 - fX) + bUpRight * (fX - iX);
g = gUpLeft * (iX + 1 - fX) + gUpRight * (fX - iX);
r = rUpLeft * (iX + 1 - fX) + rUpRight * (fX - iX);
outRowPointer[0][j * 3 + 0] = b;
outRowPointer[0][j * 3 + 1] = g;
outRowPointer[0][j * 3 + 2] = r;
}
jpeg_write_scanlines(&out, outRowPointer, 1);
//free memory
free(inRowPointer[0]);
free(baseInRowPointer[0]);
free(outRowPointer[0]);
// close resource
jpeg_finish_decompress(&in);
jpeg_destroy_decompress(&in);
jpeg_finish_compress(&out);
jpeg_destroy_compress(&out);
return true;
}
我對上面的代碼中的一些問題:
我不明白爲什麼筆者說
"zoom out picture. the factor should between 0.5 and 1.0. It can be 0.5, but can not be 1.0."
,如果我使用此代碼與任何其他因素0.2
或2
(變焦發生什麼)?當我在下面的錯誤處理中使用
jpeg_destroy_decompress(&in); jpeg_destroy_compress(&out);
時,是否有任何潛在的問題?當我使用因子是
0.23
時,它經常發生錯誤,並且結果圖像被損壞。我怎樣才能解決它,我真的想要擴大任何因素。最後,如果有人有任何其他算法或庫來縮放jpeg,那會給出最佳性能,請介紹一下。
非常感謝!
Ť&Ť
'jmp_buf setjmp_buffer;'。這足以告訴你;這不是好的代碼。 – MSalters