123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- #include "deAi7Thumb.h"
- #include <atlimage.h>
- //! Utility function to convert the argument of any type to a string
- template<typename T>
- std::string toString(const T& arg)
- {
- std::ostringstream os;
- os << arg;
- return os.str();
- }
- // Decode a Hex string.
- string decodeHex(const byte* src, long srcSize)
- {
- // 00000030h: 00 01 02 03 04 05 06 07 08 09 10 10 10 10 10 10 ;
- // 00000040h: 10 0D 0A 0B 0C 0D 0E 0F 10 10 10 10 10 10 10 10 ;
- // 00000050h: 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 ;
- // 00000060h: 10 10 0D 0A 0B 0C 0D 0E 0F 10 10 10 10 10 10 10 ;
- // create decoding table
- byte invalid = 16;
- byte decodeHexTable[256];
- for (long i = 0; i < 256; i++) decodeHexTable[i] = invalid;
- for (byte i = 0; i < 10; i++) decodeHexTable[static_cast<byte>('0') + i] = i;
- for (byte i = 0; i < 6; i++) decodeHexTable[static_cast<byte>('A') + i] = i + 10;
- for (byte i = 0; i < 6; i++) decodeHexTable[static_cast<byte>('a') + i] = i + 10;
- // calculate dest size
- long validSrcSize = 0;
- for (long srcPos = 0; srcPos < srcSize; srcPos++) {
- if (decodeHexTable[src[srcPos]] != invalid) validSrcSize++;
- }
- const long destSize = validSrcSize / 2;
- // allocate dest buffer
- string dest(destSize, '\0');
- // decode
- for (long srcPos = 0, destPos = 0; destPos < destSize; destPos++) {
- byte buffer = 0;
- for (int bufferPos = 1; bufferPos >= 0 && srcPos < srcSize; srcPos++) {
- byte srcValue = decodeHexTable[src[srcPos]];
- if (srcValue == invalid) continue;
- buffer |= srcValue << (bufferPos * 4);
- bufferPos--;
- }
- dest[destPos] = buffer;
- }
- return dest;
- }
- // Decode an Illustrator thumbnail that follows after %AI7_Thumbnail.
- string decodeAi7Thumbnail(const string& src)
- {
- const byte* colorTable = (BYTE*)src.c_str();
- const long colorTableSize = 256 * 3;
- if (src.size() < colorTableSize) {
- // Invalid size of AI7 thumbnail: src.size()
- return string();
- }
- const byte* imageData = (BYTE*)src.c_str() + colorTableSize;
- const long imageDataSize = src.size() - colorTableSize;
- const bool rle = (imageDataSize >= 3 && imageData[0] == 'R' && imageData[1] == 'L' && imageData[2] == 'E');
- std::string dest;
- for (long i = rle ? 3 : 0; i < imageDataSize;) {
- byte num = 1;
- byte value = imageData[i++];
- if (rle && value == 0xFD) {
- if (i >= imageDataSize) {
- // Unexpected end of image data at AI7 thumbnail.
- return string();
- }
- value = imageData[i++];
- if (value != 0xFD) {
- if (i >= imageDataSize) {
- // Unexpected end of image data at AI7 thumbnail
- return string();
- }
- num = value;
- value = imageData[i++];
- }
- }
- for (; num != 0; num--) {
- dest.append(reinterpret_cast<const char*>(colorTable + (3 * value)), 3);
- }
- }
- return string(reinterpret_cast<const char*>(dest.data()), static_cast<long>(dest.size()));
- }
- // Create a PNM image from raw RGB data.
- string makeBmp(size_t width, size_t height, const string& rgb)
- {
- const long expectedSize = static_cast<long>(width * height * 3);
- if (rgb.size() != expectedSize) {
- return string();
- }
- const std::string header = "P6\n" + toString(width) + " " + toString(height) + "\n255\n";
- const char* headerBytes = header.data();
- string dest(static_cast<long>(header.size() + rgb.size()) , '\0');
- std::copy(headerBytes, headerBytes + header.size(), dest.begin());
- std::copy(rgb.data(), rgb.data() + rgb.size(), dest.begin() + header.size());
- return dest;
- }
- bool rgb_makeBmp_tofile(string& rgb, size_t width, size_t height, const char* bmpfilename)
- {
- const long expectedSize = static_cast<long>(width * height * 3);
- FILE* bmpfile = fopen(bmpfilename , "wb");
- if ((rgb.size() != expectedSize) || (bmpfile == NULL)) {
- fclose(bmpfile);
- return false;
- }
- // BMP格式文件头
- BITMAPFILEHEADER bmph = {0x4D42, 54 , 0, 0, 54 }; // 14字节 'BM' 文件头
- BITMAPINFOHEADER bmpinf = {40, width, height, 1, 24, 0 , 0, 0, 0, 0, 0 }; // 40字节
- bmph.bfSize += rgb.size();
- fwrite(&bmph , 1, sizeof(bmph), bmpfile);
- fwrite(&bmpinf , 1, sizeof(bmpinf), bmpfile);
- // 由于前面解码的数据是RGB标准数据,而BMP存储为BGR顺序
- // 由于BMP写文件最下面先读写,要翻转
- for (size_t i = 0 ; i < rgb.size() -2 ; i += 3) {
- std::swap(rgb[i] , rgb[i + 2]);
- }
- const char* px = rgb.c_str();
- for (size_t i = height ; i > 0 ; i--) {
- fwrite(px + 3 * i * width , 1 , 3 * width, bmpfile);
- }
- fclose(bmpfile);
- return true;
- }
- bool decode_Ai7Thumb_toPng(string& AI7Thumb, size_t width, size_t height, const char* pngfilename)
- {
- // %AI7_Thumbnail: 76 128 8
- // %%BeginData: 14580 Hex Bytes
- // "%0000330000660000990000CC0033000033330033660033990033CC0033FF\n\r"
- // "%0066000066330066660066990066CC0066FF009900009933009966009999\n\r"
- // /***** 14580 Hex Bytes *****/
- // "%82A783A8A7FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFD8EFFFF\n\r";
- string hexbin = decodeHex((BYTE*)AI7Thumb.c_str() , AI7Thumb.size());
- string srgb = decodeAi7Thumbnail(hexbin);
- const char* tmpBmpFile = "tmpBmp.bmp";
- // RGB 数据写bmp文件
- rgb_makeBmp_tofile(srgb, width, height, tmpBmpFile);
- CImage image; // bmp 转换 png ,需要CImage类,头文件 atlimage.h
- image.Load(tmpBmpFile);
- image.Save(pngfilename);
- if (remove(tmpBmpFile) != 0)
- perror("Error deleting file");
- return true;
- }
|