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誤差拡散など)
*/
#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_PBM "P4\n"
#define MAGIC_BMP "BM6"
/* なんと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 *canvas, int xbytes, int height)
{
bzero(canvas, xbytes * height);
return(fread(canvas, xbytes, height, fp));
}
/* PBM形式データをESC/P形式に変換して出力 (1行分) */
void putpbm(unsigned char *canvas, 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 (canvas[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 *canvas, int width, int height)
{
fwrite(canvas, (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 *canvas;
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;
canvas = (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, canvas, xbytes, NBITS) <= 0) {
break;
}
if (debug & PBM_OUTPUT) {
debug_putpbm(canvas, width, NBITS);
}
else {
putpbm(canvas, width, NBITS);
}
}
free(canvas);
}
/* RGBをグレースケールに変換 */
#define rgb2gray(r,g,b) (( (double)(r) * 0.30 \
+ (double)(g) * 0.59 \
+ (double)(b) * 0.11) / (double)BMPMAXVAL)
/* BMP用のバッファをクリアする */
void clearbmp(float *grayscale, int width, int height)
{
int x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
grayscale[width * y + x] = 0.0;
}
}
}
/* 一度に印刷する分だけBMPファイルを読んで、グレースケールに変換 */
int fillbmp(FILE *fp, float *grayscale, int width, int height)
{
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);
/* 左右を反転して格納する */
grayscale[width * y + (width - x - 1)] += rgb2gray(r, g, b);
}
else {
/* データがないときは「白」にしておく */
grayscale[width * y + (width - x - 1)] = 1.0;
}
}
}
return(n);
}
/* 誤差拡散法 (Floyd-Steinberg) で二値化してPBM形式に変換 */
void fs_bmp2pbm(float *bmp, 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 (bmp[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 = bmp[y * width + x] - val;
if (x < width - 1) {
bmp[y * width + x + 1] += error * 7.0 / 16.0;
bmp[(y + 1) * width + x + 1] += error * 1.0 / 16.0;
}
if (x > 0) {
bmp[(y + 1) * width + x - 1] += error * 3.0 / 16.0;
}
bmp[(y + 1) * width + x] += error * 5.0 / 16.0;
bmp[y * width + x] = 0.0;
}
}
/* 最終列の誤差を次のところにコピー */
for (x = 0; x < width; x++) {
bmp[x] = bmp[height * width + x];
bmp[height * width + x] = 0.0;
}
}
/* ランダムディザ法で二値化してPBM形式に変換 */
void rd_bmp2pbm(float *bmp, 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 (bmp[y * width + x] < val) {
pbm[xbytes * y + (x / 8)] |= bit;
}
bit >>= 1;
if (bit <= 0) {
bit = 0x80;
}
bmp[y * width + x] = 0.0;
}
}
}
/* BMPファイルを二値化してESC/P形式に変換 */
void bmptoescp(FILE *fp, int q, int debug)
{
float *bmpcanvas;
unsigned char *canvas;
int width, height;
int y;
int xbytes;
/* 寸法決め打ち (^^; */
width = BMPWIDTH;
height = BMPHEIGHT;
fseek(fp, BMPSKIP, SEEK_CUR);
bmpcanvas = (float *)calloc(width * (NBITS + 1), sizeof(float));
clearbmp(bmpcanvas, width, NBITS + 1);
xbytes = (width + 7) / 8;
canvas = (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, bmpcanvas, width, NBITS) <= 0) {
break;
}
if (q == RANDOM_DITHER) {
rd_bmp2pbm(bmpcanvas, canvas, width, NBITS);
}
else {
fs_bmp2pbm(bmpcanvas, canvas, width, NBITS);
}
if (debug & PBM_OUTPUT) {
debug_putpbm(canvas, width, NBITS);
}
else {
putpbm(canvas, width, NBITS);
}
}
free(canvas);
free(bmpcanvas);
}
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_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: */