Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
/*
* bm2ecsp -- 画像ファイルをESC/P形式に変換
*
* revision history:
* 0.0: Sep. 14, 2004 by Dai ISHIJIMA
* 0.1: Sep. 16, 2004 BMPファイル対応 (FS誤差拡散など)
* 0.2: Sep. 19, 2004 PGM, PPMファイル対応
*/
#include
#include
#include
#define EOS '\0'
/* 量子化法 (BMPを変換するとき) */
#define FLOYD_STEINBERG 'f'
#define RANDOM_DITHER 'r'
/* デバッグ */
#define PBM_OUTPUT 1
/* ファイル識別 */
#define MAGIC_LENGTH 3
#define MAGIC_BMP "BM6"
#define MAGIC_PBM "P4\n"
#define MAGIC_PGM "P5\n"
#define MAGIC_PPM "P6\n"
/* なんとBMP形式は寸法その他を決め打ちだ! (苦笑) */
#define BMPWIDTH 480
#define BMPHEIGHT 640
#define BMPFILSIZ 921654
#define BMPSKIP (BMPFILSIZ - 3 * BMPWIDTH * BMPHEIGHT - MAGIC_LENGTH)
#define BMPMAXVAL 255
/* プリンタの縦ドット数 */
#define NBITS 24
/* プリンタ初期化 */
#define PINIT "\x1b@\x1bx1\x1b\x33\x18" /* ESC @ ESC x 1 ESC 3 24 */
#define BITIMG "\x1b*\x27" /* ビットイメージモード */
char *prog;
#define shift --argc; ++argv
/* PBMファイルを一度に印刷する分だけ読む */
int fillpbm(FILE *fp, unsigned char *bitmap, int xbytes, int height)
{
bzero(bitmap, xbytes * height);
return(fread(bitmap, xbytes, height, fp));
}
/* PBM形式データをESC/P形式に変換して出力 (1行分) */
void putpbm(unsigned char *bitmap, int width, int height)
{
int xbytes;
int x, y;
int xmask, ymask;
int bits;
xbytes = (width + 7) / 8;
printf("%s%c%c", BITIMG, width & 255, width / 256);
xmask = 0x80;
for (x = 0; x < width; x++) {
bits = 0;
ymask = 0x80;
for (y = 0; y < height; y++) {
if (bitmap[y * xbytes + x / 8] & xmask) {
bits |= ymask;
}
ymask >>= 1;
if (ymask == 0) {
putc(bits, stdout);
ymask = 0x80;
bits = 0;
}
}
xmask >>= 1;
if (xmask == 0) {
xmask = 0x80;
}
}
printf("\r\n");
}
/* デバッグ用 (量子化の確認など) にPBM形式データをそのまま出力 */
void debug_putpbm(unsigned char *bitmap, int width, int height)
{
fwrite(bitmap, (width + 7) / 8, height, stdout);
}
/* PBMファイルを読んで、ESC/P形式に変換 */
void pbmtoescp(FILE *fp, int debug)
{
char s[BUFSIZ];
int width, height;
int xbytes;
int y;
unsigned char *bitmap;
fgets(s, BUFSIZ, fp);
if (sscanf(s, "%d %d", &width, &height) != 2) {
fprintf(stderr, "%s: can't get image size\n", prog);
exit(1);
}
xbytes = (width + 7) / 8;
bitmap = (unsigned char *)calloc(xbytes, NBITS);
if (debug & PBM_OUTPUT) {
printf("P4\n%d %d\n", width, height);
}
else {
printf(PINIT);
}
for (y = 0; y < height; y += NBITS) {
if (fillpbm(fp, bitmap, xbytes, NBITS) <= 0) {
break;
}
if (debug & PBM_OUTPUT) {
debug_putpbm(bitmap, width, NBITS);
}
else {
putpbm(bitmap, width, NBITS);
}
}
free(bitmap);
}
/* RGBをグレースケールに変換 */
#define rgb2gray(r,g,b,m) (( (double)(r) * 0.30 \
+ (double)(g) * 0.59 \
+ (double)(b) * 0.11) / (double)(m))
/* グレースケールマップをクリアする */
void cleargraymap(float *graymap, int width, int height)
{
int x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
graymap[width * y + x] = 0.0;
}
}
}
/* 一度に印刷する分だけBMPファイルを読んで、グレースケールに変換 */
int fillbmp(FILE *fp, float *graymap, int width, int height, int maxval)
{
int x, y;
int r, g, b;
int n;
n = 0;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if ((r = getc(fp)) != EOF) { /* エエ加減なチェック (^^; */
++n;
g = getc(fp);
b = getc(fp);
/* 左右を反転して格納する */
graymap[width * y + (width - x - 1)]
+= rgb2gray(r, g, b, maxval);
}
else {
/* データがないときは「白」にしておく */
graymap[width * y + (width - x - 1)] = 1.0;
}
}
}
return(n);
}
/* 誤差拡散法 (Floyd-Steinberg) で二値化してPBM形式に変換 */
void fs_gray2pbm(float *graymap, unsigned char *pbm, int width, int height)
{
int xbytes;
int x, y;
float val, error;
int bit;
xbytes = (width + 7) / 8;
bzero(pbm, xbytes * height);
for (y = 0; y < height; y++) {
bit = 0x80;
for (x = 0; x < width; x++) {
if (graymap[y * width + x] > 0.5) {
val = 1.0;
}
else {
val = 0.0;
pbm[xbytes * y + (x / 8)] |= bit;
}
bit >>= 1;
if (bit <= 0) {
bit = 0x80;
}
error = graymap[y * width + x] - val;
if (x < width - 1) {
graymap[y * width + x + 1] += error * 7.0 / 16.0;
graymap[(y + 1) * width + x + 1] += error * 1.0 / 16.0;
}
if (x > 0) {
graymap[(y + 1) * width + x - 1] += error * 3.0 / 16.0;
}
graymap[(y + 1) * width + x] += error * 5.0 / 16.0;
graymap[y * width + x] = 0.0;
}
}
/* 最終列の誤差を次のところにコピー */
for (x = 0; x < width; x++) {
graymap[x] = graymap[height * width + x];
graymap[height * width + x] = 0.0;
}
}
/* ランダムディザ法で二値化してPBM形式に変換 */
void rd_gray2pbm(float *graymap, unsigned char *pbm, int width, int height)
{
int xbytes;
int x, y;
int bit;
float val;
xbytes = (width + 7) / 8;
bzero(pbm, xbytes * height);
for (y = 0; y < height; y++) {
bit = 0x80;
for (x = 0; x < width; x++) {
val = (double)random() / (double)RAND_MAX;
if (graymap[y * width + x] < val) {
pbm[xbytes * y + (x / 8)] |= bit;
}
bit >>= 1;
if (bit <= 0) {
bit = 0x80;
}
graymap[y * width + x] = 0.0;
}
}
}
/* BMPファイルを二値化してESC/P形式に変換 */
void bmptoescp(FILE *fp, int q, int debug)
{
float *graymap;
unsigned char *bitmap;
int width, height;
int maxval;
int y;
int xbytes;
/* 寸法決め打ち (^^; */
width = BMPWIDTH;
height = BMPHEIGHT;
maxval = BMPMAXVAL;
fseek(fp, BMPSKIP, SEEK_CUR);
graymap = (float *)calloc(width * (NBITS + 1), sizeof(float));
cleargraymap(graymap, width, NBITS + 1);
xbytes = (width + 7) / 8;
bitmap = (unsigned char *)calloc(xbytes, NBITS);
if (debug & PBM_OUTPUT) {
printf("P4\n%d %d\n", width, height);
}
else {
printf(PINIT);
}
for (y = 0; y < height; y += NBITS) {
if (fillbmp(fp, graymap, width, NBITS, maxval) <= 0) {
break;
}
if (q == RANDOM_DITHER) {
rd_gray2pbm(graymap, bitmap, width, NBITS);
}
else {
fs_gray2pbm(graymap, bitmap, width, NBITS);
}
if (debug & PBM_OUTPUT) {
debug_putpbm(bitmap, width, NBITS);
}
else {
putpbm(bitmap, width, NBITS);
}
}
free(bitmap);
free(graymap);
}
/* 一度に印刷する分だけPGMファイルを読んで、グレースケールに変換 */
int fillpgm(FILE *fp, float *graymap, int width, int height, int maxval)
{
int x, y;
int g;
int n;
n = 0;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if ((g = getc(fp)) != EOF) { /* エエ加減なチェック (^^; */
++n;
graymap[width * y + x] += (double)g / (double)maxval;
}
else {
/* データがないときは「白」にしておく */
graymap[width * y + (width - x - 1)] = 1.0;
}
}
}
return(n);
}
/* PGMファイルを読んで、ESC/P形式に変換 */
void pgmtoescp(FILE *fp, int q, int debug)
{
char s[BUFSIZ];
int width, height;
int maxval;
int xbytes;
int y;
unsigned char *bitmap;
float *graymap;
fgets(s, BUFSIZ, fp);
if (sscanf(s, "%d %d", &width, &height) != 2) {
fprintf(stderr, "%s: can't get image size\n", prog);
exit(1);
}
fgets(s, BUFSIZ, fp);
if (sscanf(s, "%d", &maxval) != 1) {
fprintf(stderr, "%s: can't get maxval\n", prog);
exit(1);
}
graymap = (float *)calloc(width * (NBITS + 1), sizeof(float));
cleargraymap(graymap, width, NBITS + 1);
xbytes = (width + 7) / 8;
bitmap = (unsigned char *)calloc(xbytes, NBITS);
if (debug & PBM_OUTPUT) {
printf("P4\n%d %d\n", width, height);
}
else {
printf(PINIT);
}
for (y = 0; y < height; y += NBITS) {
if (fillpgm(fp, graymap, width, NBITS, maxval) <= 0) {
break;
}
if (q == RANDOM_DITHER) {
rd_gray2pbm(graymap, bitmap, width, NBITS);
}
else {
fs_gray2pbm(graymap, bitmap, width, NBITS);
}
if (debug & PBM_OUTPUT) {
debug_putpbm(bitmap, width, NBITS);
}
else {
putpbm(bitmap, width, NBITS);
}
}
free(bitmap);
free(graymap);
}
/* 一度に印刷する分だけPPMファイルを読んで、グレースケールに変換 */
int fillppm(FILE *fp, float *graymap, int width, int height, int maxval)
{
int x, y;
int r, g, b;
int n;
n = 0;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if ((r = getc(fp)) != EOF) { /* エエ加減なチェック (^^; */
++n;
g = getc(fp);
b = getc(fp);
graymap[width * y + x] += rgb2gray(r, g, b, maxval);
}
else {
/* データがないときは「白」にしておく */
graymap[width * y + (width - x - 1)] = 1.0;
}
}
}
return(n);
}
/* PPMファイルを読んで、ESC/P形式に変換 */
void ppmtoescp(FILE *fp, int q, int debug)
{
char s[BUFSIZ];
int width, height;
int maxval;
int xbytes;
int y;
unsigned char *bitmap;
float *graymap;
fgets(s, BUFSIZ, fp);
if (sscanf(s, "%d %d", &width, &height) != 2) {
fprintf(stderr, "%s: can't get image size\n", prog);
exit(1);
}
fgets(s, BUFSIZ, fp);
if (sscanf(s, "%d", &maxval) != 1) {
fprintf(stderr, "%s: can't get maxval\n", prog);
exit(1);
}
graymap = (float *)calloc(width * (NBITS + 1), sizeof(float));
cleargraymap(graymap, width, NBITS + 1);
xbytes = (width + 7) / 8;
bitmap = (unsigned char *)calloc(xbytes, NBITS);
if (debug & PBM_OUTPUT) {
printf("P4\n%d %d\n", width, height);
}
else {
printf(PINIT);
}
for (y = 0; y < height; y += NBITS) {
if (fillppm(fp, graymap, width, NBITS, maxval) <= 0) {
break;
}
if (q == RANDOM_DITHER) {
rd_gray2pbm(graymap, bitmap, width, NBITS);
}
else {
fs_gray2pbm(graymap, bitmap, width, NBITS);
}
if (debug & PBM_OUTPUT) {
debug_putpbm(bitmap, width, NBITS);
}
else {
putpbm(bitmap, width, NBITS);
}
}
free(bitmap);
free(graymap);
}
/* 画像ファイルを読んでESC/Pに変換 */
void convert(FILE *fp, int q, int debug)
{
char magic[MAGIC_LENGTH];
if (fread(magic, 1, MAGIC_LENGTH, fp) != MAGIC_LENGTH) {
fprintf(stderr, "%s: can't read magic\n", prog);
exit(1);
}
if (strncmp(magic, MAGIC_PBM, MAGIC_LENGTH) == 0) { /* PBM */
pbmtoescp(fp, debug);
}
else if (strncmp(magic, MAGIC_PGM, MAGIC_LENGTH) == 0) { /* PGM */
pgmtoescp(fp, q, debug);
}
else if (strncmp(magic, MAGIC_PPM, MAGIC_LENGTH) == 0) { /* PPM */
ppmtoescp(fp, q, debug);
}
else if (strncmp(magic, MAGIC_BMP, MAGIC_LENGTH) == 0) { /* BMP */
bmptoescp(fp, q, debug);
}
else {
fprintf(stderr, "%s: unknown file format\n", prog);
exit(1);
}
exit(0);
}
void usage()
{
fprintf(stderr, "Usage: %s [-d] [-f] [-r] [file]...\n", prog);
}
int main(int argc, char *argv[])
{
int q;
int debug;
FILE *fp;
prog = *argv;
shift;
debug = 0;
q = FLOYD_STEINBERG;
while ((argc > 0) && (argv[0][0] == '-') && (argv[0][1] != EOS)) {
if (argv[0][1] == 'f') {
q = FLOYD_STEINBERG;
}
else if (argv[0][1] == 'r') {
q = RANDOM_DITHER;
}
else if (argv[0][1] == 'd') {
debug |= PBM_OUTPUT;
}
else {
usage();
exit(1);
}
shift;
}
if (argc > 0) {
while (argc > 0) {
if (argv[0][0] == '-') {
fp = stdin;
}
else if ((fp = fopen(*argv, "r")) == NULL) {
fprintf(stderr, "%s: can't open %s\n", prog, *argv);
exit(1);
}
convert(fp, q, debug);
if (argv[0][0] != '-') {
fclose(fp);
}
}
}
else {
convert(stdin, q, debug);
}
exit(0);
}
/* Local Variables: */
/* compile-command:"gcc -Wall -o bm2escp bm2escp.c" */
/* End: */