📄 bmp.c
字号:
else if (info_hdr.iSize == BIH_OS22SIZE || info_hdr.iSize == 16) bmp_type = BMPT_OS22; else bmp_type = BMPT_WIN5; if (bmp_type == BMPT_WIN4 || bmp_type == BMPT_WIN5 || bmp_type == BMPT_OS22) { read(fd, &info_hdr.iWidth, 4); read(fd, &info_hdr.iHeight, 4); read(fd, &info_hdr.iPlanes, 2); read(fd, &info_hdr.iBitCount, 2); read(fd, &info_hdr.iCompression, 4); read(fd, &info_hdr.iSizeImage, 4); read(fd, &info_hdr.iXPelsPerMeter, 4); read(fd, &info_hdr.iYPelsPerMeter, 4); read(fd, &info_hdr.iClrUsed, 4); read(fd, &info_hdr.iClrImportant, 4); read(fd, &info_hdr.iRedMask, 4); read(fd, &info_hdr.iGreenMask, 4); read(fd, &info_hdr.iBlueMask, 4); read(fd, &info_hdr.iAlphaMask, 4);#ifdef WORDS_BIGENDIAN BMPSwabLong(&info_hdr.iWidth); BMPSwabLong(&info_hdr.iHeight); BMPSwabShort(&info_hdr.iPlanes); BMPSwabShort(&info_hdr.iBitCount); BMPSwabLong(&info_hdr.iCompression); BMPSwabLong(&info_hdr.iSizeImage); BMPSwabLong(&info_hdr.iXPelsPerMeter); BMPSwabLong(&info_hdr.iYPelsPerMeter); BMPSwabLong(&info_hdr.iClrUsed); BMPSwabLong(&info_hdr.iClrImportant); BMPSwabLong(&info_hdr.iRedMask); BMPSwabLong(&info_hdr.iGreenMask); BMPSwabLong(&info_hdr.iBlueMask); BMPSwabLong(&info_hdr.iAlphaMask);#endif n_clr_elems = 4; *xres = (int) ((double)info_hdr.iXPelsPerMeter * 2.54 + 0.05) / 100; *yres = (int) ((double)info_hdr.iYPelsPerMeter * 2.54 + 0.05) / 100; } if (bmp_type == BMPT_OS22) { /* * FIXME: different info in different documents * regarding this! */ n_clr_elems = 3; } if (bmp_type == BMPT_OS21) { int16 iShort; read(fd, &iShort, 2);#ifdef WORDS_BIGENDIAN BMPSwabShort(&iShort);#endif info_hdr.iWidth = iShort; read(fd, &iShort, 2);#ifdef WORDS_BIGENDIAN BMPSwabShort(&iShort);#endif info_hdr.iHeight = iShort; read(fd, &iShort, 2);#ifdef WORDS_BIGENDIAN BMPSwabShort(&iShort);#endif info_hdr.iPlanes = iShort; read(fd, &iShort, 2);#ifdef WORDS_BIGENDIAN BMPSwabShort(&iShort);#endif info_hdr.iBitCount = iShort; info_hdr.iCompression = BMPC_RGB; n_clr_elems = 3; } if (info_hdr.iBitCount != 1 && info_hdr.iBitCount != 4 && info_hdr.iBitCount != 8 && info_hdr.iBitCount != 16 && info_hdr.iBitCount != 24 && info_hdr.iBitCount != 32) { ps_error(psdoc, PS_RuntimeError, _("Cannot process bmp file with bit count %d."), info_hdr.iBitCount); close(fd); return 0; } *w = info_hdr.iWidth; *h = (info_hdr.iHeight > 0) ? info_hdr.iHeight : -info_hdr.iHeight; switch (info_hdr.iBitCount) { case 1: case 4: case 8: *spp = 1; *bps = info_hdr.iBitCount; /* Allocate memory for colour table and read it. */ if (info_hdr.iClrUsed) clr_tbl_size = ((uint32)(1 << *bps) < info_hdr.iClrUsed) ? 1 << *bps : info_hdr.iClrUsed; else clr_tbl_size = 1 << *bps; clr_tbl = (unsigned char *) psdoc->malloc(psdoc, n_clr_elems * clr_tbl_size, _("Allocate memory for color table.")); if (!clr_tbl) { ps_error(psdoc, PS_MemoryError, _("Cannot allocate memory for color table.")); goto bad; } /*printf ("n_clr_elems: %d, clr_tbl_size: %d\n", n_clr_elems, clr_tbl_size); */ lseek(fd, BFH_SIZE + info_hdr.iSize, SEEK_SET); read(fd, clr_tbl, n_clr_elems * clr_tbl_size); /*for(clr = 0; clr < clr_tbl_size; ++clr) { printf ("%d: r: %d g: %d b: %d\n", clr, clr_tbl[clr*n_clr_elems+2], clr_tbl[clr*n_clr_elems+1], clr_tbl[clr*n_clr_elems]); }*/ break; case 16: case 24: *spp = 3; *bps = info_hdr.iBitCount / *spp; break; case 32: *spp = 3; *bps = 8; break; default: break; } stride = (*w * *spp * *bps + 7) / 8; /*printf ("w: %d, h: %d, spp: %d, bps: %d, colorspace: %d\n", *w, *h, *spp, *bps, info_hdr.iCompression); */ // detect old style bitmask images if (info_hdr.iCompression == BMPC_RGB && info_hdr.iBitCount == 16) { /*printf ("implicit non-RGB image\n"); */ info_hdr.iCompression = BMPC_BITFIELDS; info_hdr.iBlueMask = 0x1f; info_hdr.iGreenMask = 0x1f << 5; info_hdr.iRedMask = 0x1f << 10; } /* -------------------------------------------------------------------- */ /* Read uncompressed image data. */ /* -------------------------------------------------------------------- */ switch (info_hdr.iCompression) { case BMPC_BITFIELDS: // we convert those to RGB for easier use *bps = 8; stride = (*w * *spp * *bps + 7) / 8; case BMPC_RGB: { uint32 file_stride = ((*w * info_hdr.iBitCount + 7) / 8 + 3) / 4 * 4; /*printf ("bitcount: %d, stride: %d, file stride: %d\n", info_hdr.iBitCount, stride, file_stride); printf ("red mask: %x, green mask: %x, blue mask: %x\n", info_hdr.iRedMask, info_hdr.iGreenMask, info_hdr.iBlueMask); */ data = (unsigned char *) psdoc->malloc(psdoc, stride * *h, _("Allocate memory for image buffer.")); if (!data) { ps_error(psdoc, PS_MemoryError, _("Cannot allocate memory for image buffer.")); goto bad1; } for (row = 0; row < *h; row++) { uint32 offset; if (info_hdr.iHeight > 0) offset = file_hdr.iOffBits + (*h - row - 1) * file_stride; else offset = file_hdr.iOffBits + row * file_stride; if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { ps_error(psdoc, PS_Warning, _("Scanline %lu: Seek error."), (unsigned long) row); } if (read(fd, data + stride*row, stride) < 0) { ps_error(psdoc, PS_Warning, _("Scanline %lu: Read error."), (unsigned long) row); } // convert to RGB if (info_hdr.iCompression == BMPC_BITFIELDS) { unsigned char* row_ptr = data + stride*row; unsigned char* r16_ptr = row_ptr + file_stride - 2; unsigned char* rgb_ptr = row_ptr + stride - 3; int r_shift = last_bit_set (info_hdr.iRedMask) - 7; int g_shift = last_bit_set (info_hdr.iGreenMask) - 7; int b_shift = last_bit_set (info_hdr.iBlueMask) - 7; for ( ; rgb_ptr >= row_ptr; r16_ptr -= 2, rgb_ptr -= 3) { int val = (r16_ptr[0] << 0) + (r16_ptr[1] << 8); if (r_shift > 0) rgb_ptr[0] = (val & info_hdr.iRedMask) >> r_shift; else rgb_ptr[0] = (val & info_hdr.iRedMask) << -r_shift; if (g_shift > 0) rgb_ptr[1] = (val & info_hdr.iGreenMask) >> g_shift; else rgb_ptr[1] = (val & info_hdr.iGreenMask) << -g_shift; if (b_shift > 0) rgb_ptr[2] = (val & info_hdr.iBlueMask) >> b_shift; else rgb_ptr[2] = (val & info_hdr.iBlueMask) << -b_shift; } } else rearrangePixels(data + stride*row, *w, info_hdr.iBitCount); } } break; /* -------------------------------------------------------------------- */ /* Read compressed image data. */ /* -------------------------------------------------------------------- */ case BMPC_RLE4: case BMPC_RLE8: { uint32 i, j, k, runlength, x; uint32 compr_size, uncompr_size; unsigned char *comprbuf; unsigned char *uncomprbuf;// printf ("RLE%s compressed\n", info_hdr.iCompression == BMPC_RLE4 ? "4" : "8"); compr_size = file_hdr.iSize - file_hdr.iOffBits; uncompr_size = *w * *h; comprbuf = (unsigned char *) psdoc->malloc(psdoc, compr_size, _("Allocate memory for compressed scanline buffer.")); if (!comprbuf) { ps_error(psdoc, PS_MemoryError, _("Cannot allocate memory for compressed scanline buffer")); goto bad1; } uncomprbuf = (unsigned char *) psdoc->malloc(psdoc, uncompr_size, _("Allocate memory for uncompressed scanline buffer.")); if (!uncomprbuf) { ps_error(psdoc, PS_MemoryError, _("Cannot allocate memory for uncompressed scanline buffer")); goto bad1; } lseek(fd, file_hdr.iOffBits, SEEK_SET); read(fd, comprbuf, compr_size); i = j = x = 0; while( j < uncompr_size && i < compr_size ) { if ( comprbuf[i] ) { runlength = comprbuf[i++]; for ( k = 0; runlength > 0 && j < uncompr_size && i < compr_size && x < *w; ++k, ++x) { if (info_hdr.iBitCount == 8) uncomprbuf[j++] = comprbuf[i]; else { if ( k & 0x01 ) uncomprbuf[j++] = comprbuf[i] & 0x0F; else uncomprbuf[j++] = (comprbuf[i] & 0xF0) >> 4; } runlength--; } i++; } else { i++; if ( comprbuf[i] == 0 ) { /* Next scanline */ i++; x = 0;; } else if ( comprbuf[i] == 1 ) /* End of image */ break; else if ( comprbuf[i] == 2 ) { /* Move to... */ i++; if ( i < compr_size - 1 ) { j += comprbuf[i] + comprbuf[i+1] * *w; i += 2; } else break; } else { /* Absolute mode */ runlength = comprbuf[i++]; for ( k = 0; k < runlength && j < uncompr_size && i < compr_size; k++, x++) { if (info_hdr.iBitCount == 8) uncomprbuf[j++] = comprbuf[i++]; else { if ( k & 0x01 ) uncomprbuf[j++] = comprbuf[i++] & 0x0F; else uncomprbuf[j++] = (comprbuf[i] & 0xF0) >> 4; } } /* word boundary alignment */ if (info_hdr.iBitCount == 4) k /= 2; if ( k & 0x01 ) i++; } } } psdoc->free(psdoc, comprbuf); data = (unsigned char *) psdoc->malloc(psdoc, uncompr_size, _("Allocate memory for final uncompressed scanline buffer.")); if (!data) { ps_error(psdoc, PS_MemoryError, _("Cannot allocate memory for final uncompressed scanline buffer.")); goto bad1; } // TODO: suboptimal, later improve the above to yield the corrent orientation natively for (row = 0; row < *h; ++row) { memcpy (data + row * *w, uncomprbuf + (*h - 1 - row) * *w, *w); rearrangePixels(data + row * *w, *w, info_hdr.iBitCount); } psdoc->free(psdoc, uncomprbuf); *bps = 8; } break; } /* switch */ /* export the table */ *color_table = clr_tbl; *color_table_size = clr_tbl_size; *color_table_elements = n_clr_elems; goto bad;bad1: if (clr_tbl) psdoc->free(psdoc, clr_tbl); clr_tbl = NULL;bad: close(fd); return data;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -