/* --------------------------------------- 读取文件数据 --------------------------------------- */ static bool_t iPAK_IPAC_getFileData ( __CR_IN__ iPACKAGE* that, __CR_OT__ sBUFFER* buff, __CR_IN__ int64u index, __CR_IN__ bool_t hash ) { int64u size; void_t* data; iDATIN* file; iPAK_IPAC* real; sPAK_FILE* item; /* 定位文件索引 */ CR_NOUSE(hash); real = (iPAK_IPAC*)that; if (index >= real->m_cnt) return (FALSE); item = real->pack.__filelst__; item += (uint_t)index; /* 获取文件数据 (0大小文件分配1个字节) */ size = item->size; if (size == 0) { data = mem_malloc(1); if (data == NULL) return (FALSE); size = 1; *(byte_t*)data = 0x00; } else { data = mem_malloc64(size); if (data == NULL) return (FALSE); file = real->m_file; /* 定位到文件并读起数据 */ if (!CR_VCALL(file)->seek64(file, item->offs, SEEK_SET)) goto _failure; if (CR_VCALL(file)->read(file, data, (leng_t)size) != (leng_t)size) goto _failure; } /* 返回文件数据 */ return (buffer_init(buff, data, (leng_t)size, TRUE)); _failure: mem_free(data); return (FALSE); }
/* ======================================= KrKr XP3 文件读取 ======================================= */ CR_API sFMT_PRT* load_krkr_xp3 ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { int16u idx; int16u len; int32u attr; int64u tots; int64u tsz1; int64u tsz2; int64u pksz; int64u unsz; leng_t back; sARRAY list; byte_t* info; byte_t* pntr; wide_t* name; sXP3_HDR head; iPAK_XP3* port; sFMT_PRT* rett; sPAK_XP3_FILE temp; /* 必须使用自己私有的读取接口 */ datin = create_file_inX(param); if (datin == NULL) return (NULL); array_initT(&list, sPAK_XP3_FILE); list.free = xp3_free; /* 读取文件头信息 */ if (!(CR_VCALL(datin)->geType(datin, &head, sXP3_HDR))) goto _failure1; if (mem_cmp(head.tag, "XP3\r\n \n\x1A\x8B\x67\x01", 11) != 0) goto _failure1; head.idx_pos = QWORD_LE(head.idx_pos); /* 读取文件索引表 */ if (!CR_VCALL(datin)->seek64(datin, head.idx_pos, SEEK_SET)) goto _failure1; if (!CR_VCALL(datin)->getb_no(datin, head.tag)) goto _failure1; if (head.tag[0]) { /* ZLib 压缩的索引表 */ if (!CR_VCALL(datin)->getq_le(datin, &pksz)) goto _failure1; if (!CR_VCALL(datin)->getq_le(datin, &unsz)) goto _failure1; pntr = (byte_t*)mem_malloc64(pksz); if (pntr == NULL) goto _failure1; back = CR_VCALL(datin)->read(datin, pntr, (leng_t)pksz); if (back != (leng_t)pksz) { mem_free(pntr); goto _failure1; } info = (byte_t*)mem_malloc64(unsz); if (info == NULL) { mem_free(pntr); goto _failure1; } back = uncompr_zlib(info, (leng_t)unsz, pntr, (leng_t)pksz); mem_free(pntr); if (back != (leng_t)unsz) goto _failure2; } else { /* 直接读起索引表 */ if (!CR_VCALL(datin)->getq_le(datin, &unsz)) goto _failure1; info = (byte_t*)mem_malloc64(unsz); if (info == NULL) goto _failure1; back = CR_VCALL(datin)->read(datin, info, (leng_t)unsz); if (back != (leng_t)unsz) goto _failure2; } /* 设置加密类型 (如果有的话) */ if (param->aprm != NULL && *(byte_t*)param->aprm != 0x00) attr = PAK_FILE_ENC; else attr = 0; /* 加载文件信息表 */ for (pntr = info, pksz = 0; pksz < unsz;) { /* "File" 数据块 */ if (mem_cmp(pntr, "File", 4) != 0) break; mem_cpy(&tots, pntr + 4, sizeof(int64u)); tots = QWORD_LE(tots); pntr += 12; pksz += 12; if (tots <= 12 + 22 + 12 + 28 || tots > unsz - pksz) goto _failure2; /* "info" 文件总信息 */ if (mem_cmp(pntr, "info", 4) != 0) goto _failure2; mem_cpy(&tsz1, pntr + 4, sizeof(int64u)); tsz1 = QWORD_LE(tsz1); pntr += 12; pksz += 12; if (tsz1 <= 22 || tsz1 > tots - 12 - 12 - 28) goto _failure2; /* 填充一些文件信息结构成员 */ struct_zero(&temp, sPAK_XP3_FILE); mem_cpy(&temp.protect, pntr + 0, sizeof(int32u)); mem_cpy(&temp.base.size, pntr + 4, sizeof(int64u)); mem_cpy(&temp.base.pack, pntr + 12, sizeof(int64u)); temp.base.skip = sizeof(sPAK_XP3_FILE); temp.base.attr = attr; temp.protect = DWORD_LE(temp.protect); temp.base.size = QWORD_LE(temp.base.size); temp.base.pack = QWORD_LE(temp.base.pack); /* 读取文件名 UTF-16 无\0结尾 */ mem_cpy(&len, pntr + 20, sizeof(int16u)); len = WORD_LE(len); if ((int64u)len > tsz1 - 22) goto _failure2; name = str_allocW(len + 1); if (name == NULL) goto _failure2; for (idx = 0; idx < len; idx++) { mem_cpy(&name[idx], pntr + 22 + ((leng_t)idx) * 2, 2); name[idx] = WORD_LE(name[idx]); } name[idx] = 0x0000; temp.base.name = utf16_to_utf8(name); mem_free(name); if (temp.base.name == NULL) goto _failure2; pntr += (leng_t)tsz1; pksz += (leng_t)tsz1; /* "segm" 文件分段信息 */ if (mem_cmp(pntr, "segm", 4) != 0) goto _failure3; mem_cpy(&tsz2, pntr + 4, sizeof(int64u)); tsz2 = QWORD_LE(tsz2); pntr += 12; pksz += 12; if (tsz2 < 28 || tsz2 % 28 != 0 || tsz2 > tots - 12 - tsz1 - 12) goto _failure3; /* 读取所有分段信息 */ temp.segm_lst = mem_talloc64(tsz2 / 28, sPAK_XP3_SEGM); if (temp.segm_lst == NULL) goto _failure3; temp.segm_cnt = (leng_t)(tsz2 / 28); mem_cpy(temp.segm_lst, pntr, (leng_t)tsz2); for (back = 0; back < temp.segm_cnt; back++) { temp.segm_lst[back].zlib = DWORD_LE(temp.segm_lst[back].zlib); temp.segm_lst[back].offset = QWORD_LE(temp.segm_lst[back].offset); temp.segm_lst[back].unsize = QWORD_LE(temp.segm_lst[back].unsize); temp.segm_lst[back].pksize = QWORD_LE(temp.segm_lst[back].pksize); if (temp.segm_lst[back].unsize > temp.base.size) goto _failure4; if (temp.segm_lst[back].pksize > temp.base.pack) goto _failure4; } pntr += (leng_t)tsz2; pksz += (leng_t)tsz2; /* 其他非重要数据段 */ if (tots > 12 + tsz1 + 12 + tsz2) { tots -= 12 + tsz1 + 12 + tsz2; /* "adlr" 附加数据 */ if (mem_cmp(pntr, "adlr", 4) == 0) { if (tots < 16) goto _failure4; mem_cpy(&temp.adlr_key, pntr + 4, sizeof(int32u)); temp.adlr_key = DWORD_LE(temp.adlr_key); } pntr += (leng_t)tots; pksz += (leng_t)tots; } /* 用第一段设置剩下的成员 */ temp.base.offs = temp.segm_lst[0].offset; if (temp.segm_lst[0].zlib) { if (attr == 0) temp.base.memo = "ZLib"; else temp.base.memo = "ZLib + Encrypt"; temp.base.attr |= PAK_FILE_CMP; } else { if (attr == 0) temp.base.memo = "Store"; else temp.base.memo = "Encrypt"; } /* 文件信息压入列表 */ if (array_push_growT(&list, sPAK_XP3_FILE, &temp) == NULL) goto _failure4; } mem_free(info); /* 固定一下列表大小 */ if (!array_no_growT(&list, sPAK_XP3_FILE)) goto _failure1; /* 生成读包接口对象 */ port = struct_new(iPAK_XP3); if (port == NULL) goto _failure1; port->m_file = datin; port->m_cnt = array_get_sizeT(&list, sPAK_XP3_FILE); port->pack.__filelst__ = array_get_dataT(&list, sPAK_FILE); port->pack.__vptr__ = &s_pack_vtbl; if (!pack_init_list((iPACKAGE*)port, TRUE)) { mem_free(port); goto _failure1; } /* 设置解密回调 (传入名称字符串) */ if (attr != 0) { decode_setup(port, (ansi_t*)param->aprm); } else { port->decode_file = NULL; port->decode_block = NULL; } /* 返回读取的文件数据 */ rett = struct_new(sFMT_PRT); if (rett == NULL) { iPAK_XP3_release((iPACKAGE*)port); return (NULL); } rett->type = CR_FMTZ_PRT; rett->port = (iPORT*)port; rett->more = "iPACKAGE"; rett->infor = "KiriKiri2 XP3 Archive (XP3)"; return (rett); _failure4: mem_free(temp.segm_lst); _failure3: mem_free(temp.base.name); _failure2: mem_free(info); _failure1: array_freeT(&list, sPAK_XP3_FILE); CR_VCALL(datin)->release(datin); return (NULL); }
/* --------------------------------------- 读取文件数据 --------------------------------------- */ static bool_t iPAK_RAR_getFileData ( __CR_IN__ iPACKAGE* that, __CR_OT__ sBUFFER* buff, __CR_IN__ int64u index, __CR_IN__ bool_t hash ) { sint_t rett; int64u size; void_t* data; iPAK_RAR* real; sPAK_RAR_FILE* item; RARHeaderDataEx info; RAROpenArchiveDataEx open; /* 定位文件索引 */ CR_NOUSE(hash); real = (iPAK_RAR*)that; if (index >= real->m_cnt) return (FALSE); item = (sPAK_RAR_FILE*)real->pack.__filelst__; item += (leng_t)index; /* 获取文件数据 (0大小文件分配1个字节) */ size = item->base.size; if (size == 0) { data = mem_malloc(1); if (data == NULL) return (FALSE); size = 1; *(byte_t*)data = 0x00; } else { real->m_temp = data = mem_malloc64(size); if (data == NULL) return (FALSE); /* RAR 只能顺序读取文件 */ if (real->m_rar == NULL || item->id < real->m_cur) { /* 需要重新打开封包 */ if (real->m_rar != NULL) { RARCloseArchive(real->m_rar); real->m_rar = NULL; } struct_zero(&open, RAROpenArchiveDataEx); if (real->m_ansi != NULL) open.ArcName = real->m_ansi; else open.ArcNameW = real->m_wide; open.OpenMode = RAR_OM_EXTRACT; open.Callback = rar_mem_copy; open.UserData = (LPARAM)(&real->m_temp); real->m_rar = RAROpenArchiveEx(&open); if (real->m_rar == NULL) goto _failure1; if (real->m_pass != NULL) RARSetPassword(real->m_rar, real->m_pass); real->m_cur = 0; } /* 定位到指定文件 */ struct_zero(&info, RARHeaderDataEx); while (real->m_cur != item->id) { rett = RARReadHeaderEx(real->m_rar, &info); if (rett != ERAR_SUCCESS) goto _failure2; rett = RARProcessFile(real->m_rar, RAR_SKIP, NULL, NULL); if (rett != ERAR_SUCCESS && rett != ERAR_BAD_DATA) goto _failure2; real->m_cur += 1; } /* 测试目标文件就不会有磁盘操作了 */ rett = RARReadHeaderEx(real->m_rar, &info); if (rett != ERAR_SUCCESS) goto _failure2; rett = RARProcessFile(real->m_rar, RAR_TEST, NULL, NULL); if (rett != ERAR_SUCCESS) goto _failure2; real->m_cur += 1; } /* 返回文件数据 */ return (buffer_init(buff, data, (leng_t)size, TRUE)); _failure2: RARCloseArchive(real->m_rar); real->m_rar = NULL; _failure1: real->m_cur = (leng_t)-1; mem_free(data); return (FALSE); }
/* --------------------------------------- 读取文件数据 --------------------------------------- */ static bool_t iPAK_XP3_getFileData ( __CR_IN__ iPACKAGE* that, __CR_OT__ sBUFFER* buff, __CR_IN__ int64u index, __CR_IN__ bool_t hash ) { leng_t pntr; leng_t back; leng_t segm; int64u pack; int64u size; void_t* temp; void_t* data; iDATIN* file; iPAK_XP3* real; sPAK_XP3_FILE* item; /* 定位文件索引 */ CR_NOUSE(hash); real = (iPAK_XP3*)that; if (index >= real->m_cnt) return (FALSE); item = (sPAK_XP3_FILE*)real->pack.__filelst__; item += (leng_t)index; /* 获取文件数据 (0大小文件分配1个字节) */ size = item->base.size; if (size == 0) { data = mem_malloc(1); if (data == NULL) return (FALSE); size = 1; *(byte_t*)data = 0x00; } else { pack = item->base.pack; temp = mem_malloc64(pack); if (temp == NULL) return (FALSE); data = mem_malloc64(size); if (data == NULL) goto _failure1; file = real->m_file; /* 定位到文件并读起数据 */ for (pntr = 0, segm = 0; segm < item->segm_cnt; segm++) { /* 逐块读取文件 */ if (!CR_VCALL(file)->seek64(file, item->segm_lst[segm].offset, SEEK_SET)) goto _failure2; /* 是否为 ZLib 压缩 */ if (item->segm_lst[segm].zlib) { back = CR_VCALL(file)->read(file, temp, (leng_t)item->segm_lst[segm].pksize); if (back != (leng_t)item->segm_lst[segm].pksize) goto _failure2; back = uncompr_zlib((byte_t*)data + pntr, (leng_t)size - pntr, temp, back); if (back != (leng_t)item->segm_lst[segm].unsize) goto _failure2; } else { back = CR_VCALL(file)->read(file, (byte_t*)data + pntr, (leng_t)item->segm_lst[segm].unsize); if (back != (leng_t)item->segm_lst[segm].unsize) goto _failure2; } /* 数据块解密 */ if (real->decode_block != NULL) real->decode_block((byte_t*)data + pntr, back, pntr, item); pntr += back; } /* 整个文件解密 */ if (real->decode_file != NULL) real->decode_file(data, (leng_t)size, item); mem_free(temp); } /* 返回文件数据 */ return (buffer_init(buff, data, (leng_t)size, TRUE)); _failure2: mem_free(data); _failure1: mem_free(temp); return (FALSE); }
/* ======================================= PNG 文件读取 ======================================= */ CR_API sFMT_PIC* load_cr_png ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { leng_t nbpl; leng_t sbpp; leng_t dptr; uint_t fcrh; uint_t index; uchar* image; uchar* sdata; uchar* ddata; leng_t dsize; int32u ssize; uint_t ww, hh; byte_t pal[768]; /* ----------- */ fsize_t fsze; sPNG_HDR head; sFMT_PIC* rett; sFMT_FRAME temp; /* 这个参数可能为空 */ if (datin == NULL) return (NULL); /* 读取 & 检查头部 */ if (!(CR_VCALL(datin)->geType(datin, &head, sPNG_HDR))) return (NULL); if (mem_cmp(&head, "\x89PNG\r\n\x1A\n\0\0\0\x0DIHDR", 16) != 0) return (NULL); if (head.info.compr != 0 || head.info.filter != 0 || head.info.interlace != 0) return (NULL); /* 对宽高的截断检查 */ if (cut_int32_u(&ww, DWORD_BE(head.info.w))) return (NULL); if (cut_int32_u(&hh, DWORD_BE(head.info.h))) return (NULL); /* 生成图片对象 */ mem_zero(temp.wh, sizeof(temp.wh)); switch (head.info.color) { case 0: /* 灰度图像 */ if (head.info.depth != 1 && head.info.depth != 2 && head.info.depth != 4 && head.info.depth != 8 && head.info.depth != 16) return (NULL); fcrh = CR_INDEX8; temp.fmt = CR_PIC_GREY; temp.bpp = head.info.depth; temp.clr = "I"; temp.wh[0] = head.info.depth; break; case 2: /* 真彩图像 */ if (head.info.depth != 8 && head.info.depth != 16) return (NULL); fcrh = CR_ARGB888; temp.fmt = CR_PIC_ARGB; temp.bpp = head.info.depth * 3; temp.clr = "BGR"; temp.wh[0] = head.info.depth; temp.wh[1] = head.info.depth; temp.wh[2] = head.info.depth; break; case 3: /* 索引图像 */ if (head.info.depth != 1 && head.info.depth != 2 && head.info.depth != 4 && head.info.depth != 8) return (NULL); fcrh = CR_INDEX8; temp.fmt = CR_PIC_PALS; temp.bpp = head.info.depth; temp.clr = "P"; temp.wh[0] = head.info.depth; break; case 4: /* α灰度图像 */ if (head.info.depth != 8 && head.info.depth != 16) return (NULL); fcrh = CR_ARGB8888; temp.fmt = CR_PIC_GREY; temp.bpp = head.info.depth * 2; temp.clr = "AI"; temp.wh[0] = head.info.depth; temp.wh[1] = head.info.depth; break; case 6: /* α真彩图像 */ if (head.info.depth != 8 && head.info.depth != 16) return (NULL); fcrh = CR_ARGB8888; temp.fmt = CR_PIC_ARGB; temp.bpp = head.info.depth * 4; temp.clr = "ABGR"; temp.wh[0] = head.info.depth; temp.wh[1] = head.info.depth; temp.wh[2] = head.info.depth; temp.wh[3] = head.info.depth; break; default: return (NULL); } sbpp = (temp.bpp - 1) / 8 + 1; temp.pic = image_new(0, 0, ww, hh, fcrh, FALSE, 4); if (temp.pic == NULL) return (NULL); /* 生成灰度调色板 */ if (temp.fmt == CR_PIC_GREY) pal_set_gray8(temp.pic->pal, 256); /* 分配 IDAT 的内存 */ fsze = dati_get_size(datin); if (fsze <= sizeof(sPNG_HDR) + sizeof(sIEND) * 2) goto _failure1; fsze -= sizeof(sPNG_HDR) + sizeof(sIEND) * 2; ddata = (byte_t*)mem_malloc64(fsze); if (ddata == NULL) goto _failure1; dsize = (leng_t)fsze; /* 读取数据块 */ dptr = 0; fcrh = 256; /* 这个保存调色板颜色数 */ do { /* 数据块大小 */ if (!(CR_VCALL(datin)->geType(datin, &head.info, sCHUNK))) goto _failure2; ssize = DWORD_BE(head.info.head.size); if (ssize > fsze) goto _failure2; if (head.info.head.name == mk_tag4("PLTE")) { /* 调色板, 安全检查 */ if (ssize > 768 || ssize % 3 != 0) goto _failure2; if (CR_VCALL(datin)->read(datin, pal, ssize) != ssize) goto _failure2; /* 转换到 4B 格式 */ fcrh = (uint_t)ssize / 3; pal_3b_to_4b_sw(temp.pic->pal, pal, fcrh); } else if (head.info.head.name == mk_tag4("IDAT")) { /* 检查缓冲溢出 */ if (dsize < ssize) goto _failure2; if (CR_VCALL(datin)->read(datin, ddata + dptr, ssize) != ssize) goto _failure2; dptr += ssize; dsize -= ssize; } else if (head.info.head.name == mk_tag4("tRNS")) { /* 透明数据 */ if (head.info.color == 0) { if (ssize != 2) goto _failure2; if (CR_VCALL(datin)->read(datin, pal, 2) != 2) goto _failure2; /* 调色板的这个颜色为透明色 */ if (head.info.depth != 16) temp.pic->pal[pal[1]] &= CDWORD_LE(0x00FFFFFFUL); } else if (head.info.color == 2) { if (ssize != 6) goto _failure2; if (CR_VCALL(datin)->read(datin, pal, 6) != 6) goto _failure2; /* 这个颜色为透明色, 这里只能展开来写 否则 C++Builder 2010 编译器编译时会崩溃 */ if (head.info.depth != 16) { temp.pic->keycolor = pal[1]; temp.pic->keycolor <<= 8; temp.pic->keycolor |= pal[3]; temp.pic->keycolor <<= 8; temp.pic->keycolor |= pal[5]; temp.pic->keycolor |= 0xFF000000UL; temp.pic->keycolor = DWORD_LE(temp.pic->keycolor); } } else if (head.info.color == 3) { if (ssize > fcrh) goto _failure2; if (CR_VCALL(datin)->read(datin, pal, ssize) != ssize) goto _failure2; /* 设置调色板的 Alpha 通道 */ for (fcrh = (uint_t)ssize, index = 0; index < fcrh; index++) ((uchar*)temp.pic->pal)[index * 4 + 3] = pal[index]; } else { goto _failure2; } } else { /* 跳过其他数据块 */ if (!CR_VCALL(datin)->seek(datin, ssize, SEEK_CUR)) goto _failure2; } /* 跳过 CRC-32 */ if (!CR_VCALL(datin)->seek(datin, 4, SEEK_CUR)) goto _failure2; } while (head.info.head.name != mk_tag4("IEND")); /* 无 IDAT 块 */ if (dptr == 0) goto _failure2; /* 分配带 filter 的图形内存 */ if (cut_mad(&dsize, ww, sbpp * hh, hh)) goto _failure2; sdata = (byte_t*)mem_malloc(dsize); if (sdata == NULL) goto _failure2; /* 解压图形数据 */ dptr = uncompr_zlib(sdata, dsize, ddata, dptr); mem_free(ddata); ddata = sdata; if (dptr <= hh) goto _failure2; image = temp.pic->data; /* 文件解码完毕, 解析图片的像素数据 */ if (temp.pic->fmt == CR_INDEX8) { switch (head.info.depth) { case 1: if (ww % 8 == 0) nbpl = ww / 8; else nbpl = ww / 8 + 1; if (!png_filter(ddata, nbpl, 1, hh, dptr)) goto _failure2; for (index = hh; index != 0; index--) { sdata = (uchar*)font1_h2l(image, sdata, ww); image += temp.pic->bpl; } break; case 2: if (ww % 4 == 0) nbpl = ww / 4; else nbpl = ww / 4 + 1; if (!png_filter(ddata, nbpl, 1, hh, dptr)) goto _failure2; for (index = hh; index != 0; index--) { sdata = (uchar*)font2_h2l(image, sdata, ww); image += temp.pic->bpl; } break; case 4: if (ww % 2 == 0) nbpl = ww / 2; else nbpl = ww / 2 + 1; if (!png_filter(ddata, nbpl, 1, hh, dptr)) goto _failure2; for (index = hh; index != 0; index--) { sdata = (uchar*)font4_h2l(image, sdata, ww); image += temp.pic->bpl; } break; case 8: nbpl = ww; if (!png_filter(ddata, nbpl, 1, hh, dptr)) goto _failure2; for (index = hh; index != 0; index--) { mem_cpy(image, sdata, nbpl); sdata += nbpl; image += temp.pic->bpl; } break; default: case 16: nbpl = ww; nbpl *= 2; if (!png_filter(ddata, nbpl, 2, hh, dptr)) goto _failure2; for (index = hh; index != 0; index--) { for (fcrh = 0; fcrh < ww; fcrh++, sdata += 2) image[fcrh] = sdata[0]; image += temp.pic->bpl; } break; } } else { nbpl = ww * sbpp; if (!png_filter(ddata, nbpl, sbpp, hh, dptr)) goto _failure2; nbpl = ww * temp.pic->bpc; switch (head.info.color) { case 2: if (head.info.depth == 8) { /* 直接逐行复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 3) { image[dsize + 0] = sdata[2]; image[dsize + 1] = sdata[1]; image[dsize + 2] = sdata[0]; sdata += 3; } image += temp.pic->bpl; } } else { /* 跳开一个像素复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 3) { image[dsize + 0] = sdata[4]; image[dsize + 1] = sdata[2]; image[dsize + 2] = sdata[0]; sdata += 6; } image += temp.pic->bpl; } } break; case 4: if (head.info.depth == 8) { /* 直接逐行复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 4) { image[dsize + 0] = sdata[0]; image[dsize + 1] = sdata[0]; image[dsize + 2] = sdata[0]; image[dsize + 3] = sdata[1]; sdata += 2; } image += temp.pic->bpl; } } else { /* 跳开一个像素复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 4) { image[dsize + 0] = sdata[0]; image[dsize + 1] = sdata[0]; image[dsize + 2] = sdata[0]; image[dsize + 3] = sdata[2]; sdata += 4; } image += temp.pic->bpl; } } break; default: case 6: if (head.info.depth == 8) { /* 直接逐行复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 4) { image[dsize + 0] = sdata[2]; image[dsize + 1] = sdata[1]; image[dsize + 2] = sdata[0]; image[dsize + 3] = sdata[3]; sdata += 4; } image += temp.pic->bpl; } } else { /* 跳开一个像素复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 4) { image[dsize + 0] = sdata[4]; image[dsize + 1] = sdata[2]; image[dsize + 2] = sdata[0]; image[dsize + 3] = sdata[6]; sdata += 8; } image += temp.pic->bpl; } } break; } } mem_free(ddata); /* 返回读取的文件数据 */ rett = struct_new(sFMT_PIC); if (rett == NULL) goto _failure1; rett->frame = struct_dup(&temp, sFMT_FRAME); if (rett->frame == NULL) { mem_free(rett); goto _failure1; } CR_NOUSE(param); rett->type = CR_FMTZ_PIC; rett->count = 1; rett->infor = "Portable Network Graphics (PNG)"; return (rett); _failure2: mem_free(ddata); _failure1: image_del(temp.pic); return (NULL); }