当尝试通过 GD 图像旋转图像后将原始 exif 数据附加回图像时,我遇到了麻烦。
如何旋转图像
rotatedImage = gdImageRotateInterpolated(image, (360-rotationDeg)%360, 0);
imgBuffer = (unsigned char *)gdImageJpegPtr(rotatedImage, &imgSize, 85);
然后我有一个函数尝试通过将图像缓冲区与 exif 缓冲区相结合来将从原始图像中提取的 exif 数据写入旋转的图像,但在检查图像时我仍然看不到 Exif 数据。我正在使用
libexif
writeExifData(unsigned char* &imageBuffer, int &size, ExifData* exifData) {
if (!exifData) {
return;
}
TRACE("Image Size: %d", size);
// save exif data into buffer
unsigned char* buf = NULL;
unsigned int bufSize = 0;
exif_data_save_data(exifData, &buf, &bufSize);
std::vector<unsigned char> combinedBuffer(size + bufSize);
// Copy the image buffer
std::copy(imageBuffer, imageBuffer + size, combinedBuffer.begin());
// Copy the EXIF buffer
std::copy(buf, buf + bufSize, combinedBuffer.begin() + size);
unsigned char* newImageBuffer = (unsigned char*)malloc(combinedBuffer.size());
memcpy(newImageBuffer, combinedBuffer.data(), combinedBuffer.size());
imageBuffer = newImageBuffer;
size = combinedBuffer.size();
}
还有其他方法可以让新图像缓冲区包含原始图像中的所有 Exif 数据吗?
JPEG 图像格式 由许多使用标签长度值编码的片段组成。此外,EXIF 的 APP1 数据应该紧接在文件中的 SOI 标记之后,即 JPEG 的前两个字节。
exif_save_data
产生“值”部分,但您需要自己将其包装在一个段中。
因此,您可以执行以下操作:
struct jpeg_header {
uint16_t soi;
uint16_t app1;
uint16_t exif_len;
} jh = { htobe16(0xFFD8), htobe16(0xFFE1), htobe16(2 + bufSize) };
unsigned char* newImageBuffer = (unsigned char*)malloc(sizeof(jh) + size - 2 /* duplicate SOI */);
unsigned char* write = newImageBuffer;
write = std::copy(reinterpret_cast<unsigned char *>(&jh), reinterpret_cast<unsigned char *>(&jh) + sizeof(jh), write);
write = std::copy(buf, buf+bufSize, write);
write = std::copy(imageBuffer+2, imageBuffer+size, write);
return newImageBuffer;
如果您无法访问
htobe16
,您也可以使用 htons
。