/* * Photo Image Print System * Copyright (C) 2000-2004 EPSON KOWA Corporation. * Copyright (C) SEIKO EPSON CORPORATION 2000-2004. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * As a special exception, EPSON KOWA Corporation gives permission to * link the code of this program with libraries which are covered by * the EPSON KOWA PUBLIC LICENCE and distribute their linked * combinations. You must obey the GNU General Public License in all * respects for all of the code used other than the libraries which * are covered by EPSON KOWA PUBLIC LICENCE. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #ifdef _V1_SUPPORT #include #endif /* _V1_SUPPORT */ /* #include */ #include "pfpng_ext.h" #include "pfimg.h" #include "pfmem.h" #include "libprtX.h" #include "pferr.h" #include "setup.h" #include "pfatt.h" /* rgbデータ格納用bufferのサイズ */ #define DEFAULT_BUFFER_SIZE 0xfffff /* pngformat検査用bufferのサイズ */ #define PNG_CHECK_NUMBER 8 #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4) #define SHADING_OFF_FILTER(center, left1, right1, left3, right3) \ ((center * 2 + left1 + right1) * 4 + left1 + right1 - left3 - right3) / 16 enum nCONVRSION_STATUS { CONV_STATUS_INIT = 0, CONV_STATUS_PAGE_INIT, CONV_STATUS_BAND_OUT, CONV_STATUS_PAGE_END, CONV_STATUS_END, CONV_STATUS_PNG_ERROR }; /* 印刷を行うイメージ情報を格納する */ typedef struct _PNG_IMAGE_STRUCT { FILE* ifp; /* 入力ストリームへのポインタ */ HANDLE png_ptr; /* libpngで使用 */ HANDLE info_ptr; /* libpngで使用 */ int image_pass; /* Interlece対策 */ POINT image_size; /* イメージのサイズ */ POINT print_size; /* 印刷する(実際にlibraryに送り出す) イメージのサイズ */ DPOINT magnify; /* 拡大/縮小率 */ POINT negative_margin; /* マイナスマージン マージンがマイナスになる場合には,画像そのものを切る必要がある マージンがプラスの場合、ここには0が入る */ int byte_p_pixel; /* 1pixelに必要なバイト数 */ long read_line; /* 既に読み込んだラスター数 */ int num_line; /* 格納出来るラスター数 */ UCHAR** rows; /* ラスターデータ格納用buffer */ } IMG_STRUCT, *LP_IMG_STRUCT; /* Static functions */ /* mkcode_init -Libraryをロードして、初期化を行う mkcode構造体にlibraryへのポインタを格納 引数 : LP_MKC_STRUCT mkcodeの共有情報へのポインタ 戻り値 : BOOL 0 ==成功, 1==失敗 */ static BOOL mkcode_lib_init (LP_MKC_STRUCT, FILE*); /* mkcode_end -Libraryの終了処理(開放)を行い,クローズする 引数 : LP_MKC_STRUCT mkcodeの共有情報へのポインタ 戻り値 : BOOL 0 ==成功, 1==失敗 */ static BOOL mkcode_lib_end (LP_MKC_STRUCT); /* mkcode_page_init -pege毎の処理の初期化 引数 : LP_MKC_STRUCT mkcodeの共有情報へのポインタ 戻り値 : BOOL 0 ==成功, 1==失敗 */ static BOOL mkcode_page_init (LP_MKC_STRUCT); /* mkcode_page_init -pege毎の終了処理 引数 : LP_MKC_STRUCT mkcodeの共有情報へのポインタ 戻り値 : BOOL 0 ==成功, 1==失敗 */ static BOOL mkcode_page_end (LP_MKC_STRUCT, int); /* image_to_printer -イメージ変換ループの最上位関数 入力された全ファイルに対し、順に処理を行う mkcode構造体に入力ストリームへのポインタを格納 引数 : LP_MKC_STRUCT mkcodeの共有情報へのポインタ 戻り値 : BOOL 0 ==成功, 1==失敗 */ static BOOL image_to_printer (LP_MKC_STRUCT); /* image_convert_to_code -ストリーム内に存在する全画像情報に対し, 順に処理を行う 引数 : FILE* 処理するストリームへのポインタ LP_MKC_STRUCT mkcodeの共有情報へのポインタ 戻り値 : BOOL 0 ==成功, 1==失敗 */ static BOOL image_convert_to_code (FILE*, LP_MKC_STRUCT); /* load_image_init -PNGイメージの情報を得る img構造体を構築しmkcode構造体に格納 引数 : LP_IMG_STRUCT 処理対象のImage情報を格納する構造体へのポインタ LP_MKC_STRUCT mkcodeの共有情報へのポインタ 戻り値 : BOOL 0 ==成功, 1==失敗 */ static BOOL load_image_init (LP_IMG_STRUCT, LP_MKC_STRUCT); /* load_image_end -libpngの終了処理を行い, libpngの使用していた メモリーを開放する。この時点では、まだストリームを クローズしてはいない 引数 : LP_IMG_STRUCT 処理対象のImage情報を格納する構造体へのポインタ 戻り値 : void */ static void load_image_end (LP_IMG_STRUCT); /* png_setup -PNGイメージの読み込み時の仕様を決定する ここでColorならば,24bitのRGBデータを受け取る様設定し, Monochromeならば,8bitのGrayデータを受け取る様設定する 引数 : LP_IMG_STRUCT 処理対象のImage情報を格納する構造体へのポインタ char* 印刷時のformatを渡す。color及び, monoの データはlibpngが作成してくれるのさ 戻り値 : BOOL 0 ==成功, 1==失敗 */ static BOOL png_setup (LP_IMG_STRUCT, char*); /* load_image_out -実際にラスター毎にlibraryで処理を行う 拡大/縮小処理もここで行う 引数 : LP_IMG_STRUCT 処理対象のImage情報を格納する構造体へのポインタ LP_MKC_STRUCT mkcodeの共有情報へのポインタ 戻り値 : BOOL 0 ==成功, 1==失敗 */ static BOOL load_image_out (LP_IMG_STRUCT, LP_MKC_STRUCT); /* read_raster_image -1ラスター分の画像データを用意し, その先頭へのポインタを返す 引数 : LP_IMG_STRUCT 処理対象のImage情報を格納する構造体へのポインタ 戻り値 : UCHAR* データの先頭へのポインタ */ static UCHAR* read_raster_image (LP_IMG_STRUCT); static void seek_image (LP_IMG_STRUCT); /* conf_print_image -印刷サイズ等の設定 引数 : LP_PRT_STURCT 印刷モード情報 LP_IMG_STRUCT 処理対象のImage情報を格納する構造体へのポインタ 戻り値 : void */ static void conf_print_image (LP_PRT_STRUCT, LP_IMG_STRUCT); /* set_init_param -prt_initをセット 引数 : LP_LIBPRT_INIT DLL_PRT_INITに渡す引数。この構造体に値をセットする LP_PRT_STRUCT 印刷モード情報 char* 出力ファイル名(NULLならば標準出力) 戻り値 : void */ static void set_init_param (LP_LIBPRT_INIT, LP_PRT_STRUCT, FILE*); /* set_page_param -prt_pageをセット 引数 : LP_LIBPRT_PAGE DLL_PAGE_INITに渡す引数。この構造体に値をセットする LP_PRT_STRUCT 印刷モード情報 戻り値 : void */ static void set_page_param (LP_LIBPRT_PAGE, LP_PRT_STRUCT); /* set_band_param -prt_bandをセット 引数 : LP_LIBPRT_BAND DLL_BAND_OUTに渡す引数。この構造体に値をセットする LP_IMG_STRUCT 処理対象のImage情報を格納する構造体へのポインタ 戻り値 : BOOL 0 ==成功, 1==失敗 */ static BOOL set_band_param (LP_LIBPRT_BAND, LP_IMG_STRUCT); /* free_band_param -set_band_param呼び出し時に確保されたメモリーを開放 引数 : LP_LIBPRT_BAND DLL_BAND_OUTに渡す引数 戻り値 : void */ static void free_band_param (LP_LIBPRT_BAND); /* write_judge -現在の処理行と拡大率から書き込み可不可を判断する 引数 : long 作成中のラスターデータの現在行 long 処理中のイメージデータの現在行 double 拡大率(%) 戻り値 : BOOL 0 ==書き込み不可, 1==書き込み可 */ static BOOL write_judge (long, long, double); #ifdef _V1_SUPPORT /* escp_through -ESC/Pコードを読み飛ばす これは,v1との互換の為に存在し、v2では削除予定 引数 : FILE* 入力ファイルポインタ FILE* 出力ファイルポインタ char* 既に読み込んだバッファへのポインタ int 既に読み込んだバッファのサイズ 戻り値 : BOOL -1 == esc/p (not error), 1== not esc/p */ static BOOL escp_through (FILE*, FILE*, char*, int); #endif /* _V1_SUPPORT */ static BOOL band_flush (void*, HANDLE, LP_LIBPRT_BAND, UCHAR *, UCHAR *, BOOL); static void set_raster (UCHAR *, UCHAR *, int, int, double, int); /************************************************** * public functions **************************************************/ /* make_code_process -libPrtXXXにアクセスする事により,imageをESC/Pに変換する 引数 : LP_MKC_STRUCT この構造体には,必要なライブラリへのパスと 入力されたファイルのリスト、及び印刷パラメータ が予め格納されている 戻り値 : void */ BOOL make_code_process (LP_MKC_STRUCT lp_mkcode) { /* if (fork() == 0) { if (fork() == 0) { */ FILE* outfp = NULL; int eflag = 0; /* 出力先を開く */ if (lp_mkcode->output_file == NULL) { outfp = stdout; } else { /* _LPR_DIRECT -lprに直接出力する事を可能にする version2では、削除する予定 */ #ifdef _LPR_DIRECT if (strcmp (lp_mkcode->output_file, ".")) { #endif /* _LPR_DIRECT */ outfp = fopen (lp_mkcode->output_file, "wb"); if (outfp == NULL) { PF_ERROR_HANDLER (FILE_NOT_FOUND, lp_mkcode->output_file); return 1; /* exit (1); */ } #ifdef _LPR_DIRECT } else { char prt_name[107]; strcpy (prt_name, "lpr -P"); get_prt_name (prt_name + 6); outfp = popen (prt_name, "w"); if (outfp == NULL) fprintf (stderr, "PIPS Error : Not able to communicate to lpr\n"); } #endif /* _LPR_DIRECT */ } lp_mkcode->output_fp = outfp; lp_mkcode->conv_status = 0; atbmp_init (lp_mkcode->atbmp_path); /* 変換処理 */ eflag = image_to_printer (lp_mkcode); atbmp_end (); /* 終了処理 */ if (lp_mkcode->conv_status) eflag |= mkcode_lib_end (lp_mkcode); if (lp_mkcode->output_file != NULL) { #ifdef _LPR_DIRECT if (strcmp (lp_mkcode->output_file, ".")) { #endif /* not _LPR_DIRECT */ fclose (outfp); #ifdef _LPR_DIRECT } else { pclose (outfp); } #endif /* _LPR_DIRECT */ } if (eflag) { /* PF_ERROR_HANDLER (ABNORMAL_END, NULL); */ return 1; /* exit (eflag); */ } /* } exit (0); } else { int stat; wait (&stat); } */ return 0; } /************************************************** * static functions **************************************************/ static BOOL mkcode_lib_init (LP_MKC_STRUCT lp_mkcode, FILE* outfp) { void *lib_handle, *prt_handle; char *lib_path = lp_mkcode->libprt_path; INIT_FUNC func; LIBPRT_INIT prt_init; /* lib_pathによって指定されたlibraryをロードする */ lib_handle = dlopen (lib_path, RTLD_LAZY); if (lib_handle == NULL) { PF_ERROR_HANDLER (DLL_ERROR, (char*)dlerror()); return 1; } lp_mkcode->lib_handle = lib_handle; /* libraryの初期化関数呼出 */ func = (INIT_FUNC)dlsym (lib_handle, DLL_PRT_INIT); if (func == NULL) { PF_ERROR_HANDLER (DLL_ERROR, (char*)dlerror()); return 1; } /* paramater set */ set_init_param (&prt_init, lp_mkcode->lp_prtinfo, outfp); /* libraryの初期化 */ if((*func)(&prt_handle, &prt_init)) { PF_ERROR_HANDLER (LIBPRT_ERROR, lib_path); return 1; } lp_mkcode->prt_handle = prt_handle; lp_mkcode->conv_status = CONV_STATUS_INIT; return 0; } static BOOL mkcode_lib_end (LP_MKC_STRUCT lp_mkcode) { HANDLE lib_handle = lp_mkcode->lib_handle; HANDLE prt_handle = lp_mkcode->prt_handle; END_FUNC func; if (lib_handle == NULL) return 1; /* libraryの終了処理関数呼出 */ func = (END_FUNC)dlsym(lib_handle, DLL_PRT_END); if (func == NULL) { PF_ERROR_HANDLER (DLL_ERROR, (char*)dlerror ()); return 1; } /* libraryの終了処理 */ if ((*func)(prt_handle)) { PF_ERROR_HANDLER (LIBPRT_ERROR, lp_mkcode->libprt_path); return 1; } /* libraryのクローズ */ if (dlclose (lib_handle) == -1) { PF_ERROR_HANDLER (DLL_ERROR, (char*)dlerror ()); return 1; } lp_mkcode->conv_status = CONV_STATUS_END; return 0; } static BOOL mkcode_page_init (LP_MKC_STRUCT lp_mkcode) { HANDLE lib_handle = lp_mkcode->lib_handle; HANDLE prt_handle = lp_mkcode->prt_handle; PINIT_FUNC func; LIBPRT_PAGE prt_page; func = (PINIT_FUNC)dlsym (lib_handle, DLL_PAGE_INIT); if (func == NULL) { PF_ERROR_HANDLER (DLL_ERROR, (char*)dlerror ()); return 1; } /* paramater set */ set_page_param (&prt_page, lp_mkcode->lp_prtinfo); if ((*func) (prt_handle, &prt_page)) { PF_ERROR_HANDLER (LIBPRT_ERROR, lp_mkcode->libprt_path); return 1; } lp_mkcode->conv_status = CONV_STATUS_PAGE_INIT; return 0; } static BOOL mkcode_page_end (LP_MKC_STRUCT lp_mkcode, int flag) { HANDLE lib_handle = lp_mkcode->lib_handle; HANDLE prt_handle = lp_mkcode->prt_handle; PEND_FUNC func; func = (PEND_FUNC)dlsym (lib_handle, DLL_PAGE_END); if (func == NULL) { PF_ERROR_HANDLER (DLL_ERROR, (char*)dlerror()); return 1; } if ((*func) (prt_handle, flag)) { PF_ERROR_HANDLER (LIBPRT_ERROR, lp_mkcode->libprt_path); return 1; } lp_mkcode->conv_status = CONV_STATUS_PAGE_END; return 0; } /* 印刷処理ループ */ static BOOL image_to_printer (LP_MKC_STRUCT lp_mkcode) { char** input_files = lp_mkcode->input_files; BOOL eflag = 0; int in_flag, count; in_flag = count = 0; /* 入力されたファイルを全て処理するまでループ */ while (!eflag && !in_flag) { FILE *fp = NULL; /* 標準入力から */ if (input_files == NULL) { fp = stdin; in_flag = 1; } /* ファイルから */ else { fp = fopen (input_files[count], "rb"); if (fp == NULL) { PF_ERROR_HANDLER (FILE_NOT_FOUND, input_files[count]); return 1; } } eflag = image_convert_to_code (fp, lp_mkcode); if (!in_flag) { fclose(fp); if (eflag) PF_ERROR_HANDLER (CONVERT_ERROR, input_files[count]); if (input_files[++count] == NULL) in_flag = 1; } else if (eflag) { PF_ERROR_HANDLER (CONVERT_ERROR, NULL); } } return eflag; } static BOOL image_convert_to_code (FILE* fp, LP_MKC_STRUCT lp_mkcode) { IMG_STRUCT image_str; BOOL loop_flag; BOOL eflag = 0; image_str.ifp = fp; /* 現在処理中のファイルを全て処理するためにループ */ loop_flag = 1; while (loop_flag) { int stat = 0; /* 画像情報を読み込む */ stat = load_image_init (&image_str, lp_mkcode); switch (stat) { case 1: /* 読み込みエラー */ eflag = 1; case -1: /* 処理終了 */ loop_flag = 0; continue; case 0: /* 画像取り込み準備完了 */ /* libraryをロードし, 初期化 */ if (!lp_mkcode->conv_status) { if (mkcode_lib_init (lp_mkcode, lp_mkcode->output_fp)) return 1; lp_mkcode->conv_status = 1; } default: break; } /* ページ初期化処理 */ eflag = mkcode_page_init (lp_mkcode); if (eflag) break; /* ESC/Pコード書き出し */ eflag = load_image_out (&image_str, lp_mkcode); if (lp_mkcode->conv_status != CONV_STATUS_PNG_ERROR) load_image_end (&image_str); /* ページ終了処理 */ mkcode_page_end (lp_mkcode, eflag); if (eflag) break; } return eflag; } /* 入力されたPNGファイルから情報を得る */ static BOOL load_image_init (LP_IMG_STRUCT lp_image, LP_MKC_STRUCT lp_mkcode) { FILE* fp = lp_image->ifp; char header[PNG_CHECK_NUMBER]; png_uint_32 ver; char version [32]; png_structp png_ptr; png_infop info_ptr; /* Dynamic linking to PNG library. */ if (!open_png_library ()) return 1; ver = dl_png_access_version_number ( ); sprintf ( version, "%ld.%ld.%ld", ver / 10000, ( ver / 100 ) % 100, ver % 100 ); if (fread (header, sizeof (char), PNG_CHECK_NUMBER, fp) != PNG_CHECK_NUMBER) return -1; /* 入力無し(処理終了を表す) */ /* formatのチェック */ if (dl_png_sig_cmp (header, (png_size_t)0, PNG_CHECK_NUMBER)) { #ifdef _V1_SUPPORT /* ESC/Pコードを読み飛ばす これは,v1との互換の為に存在し、v2では削除予定 */ return escp_through (fp, lp_mkcode->output_fp, header, PNG_CHECK_NUMBER); #else return 1; #endif /* _V1_SUPPORT */ } /* libpngの内部情報(ハンドル)を得る。 libpngのデフォルトエラーハンドリングを使用 */ png_ptr = dl_png_create_read_struct (version, NULL, NULL, NULL); if (!png_ptr) return 1; lp_image->png_ptr = (void*)png_ptr; /* info構造体を作成 この構造体へのアクセスは、libpngの関数を使用した方が無難 */ info_ptr = dl_png_create_info_struct (png_ptr); if (!info_ptr) return 1; lp_image->info_ptr = (void*)info_ptr; /* libpng内でエラーが起こった時の為のsetjmp */ if (setjmp (png_ptr->jmpbuf)) { PF_ERROR_HANDLER (LIB_PNG_ERROR, NULL); lp_mkcode->conv_status = CONV_STATUS_PNG_ERROR; return 1; } /* pngを加工 */ return png_setup (lp_image, lp_mkcode->lp_prtinfo->ink); } static void load_image_end (LP_IMG_STRUCT lp_image) { int i; if (lp_image == NULL) return; if (lp_image->png_ptr || lp_image->info_ptr) { png_structp png_ptr = (png_structp)lp_image->png_ptr; png_infop info_ptr = (png_infop)lp_image->info_ptr; dl_png_read_end(png_ptr, info_ptr); dl_png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } for (i = 0; i < lp_image->num_line; i++) pf_mem_free (lp_image->rows[i]); pf_mem_free (lp_image->rows); /* Unlinking from PNG library. */ close_png_library (); return; } /* * png_setup -pngの設定 */ static BOOL png_setup (LP_IMG_STRUCT lp_image, char* format) { UCHAR** rows; int line, i; long width_byte; png_uint_32 width, height; int bit_depth, color_type; png_structp png_ptr = lp_image->png_ptr; png_infop info_ptr = lp_image->info_ptr; FILE* fp = lp_image->ifp; /* I/O初期化 */ dl_png_init_io (png_ptr, fp); /* 既に読み込んだ部分を教える */ dl_png_set_sig_bytes (png_ptr, PNG_CHECK_NUMBER); /* pngの情報を得る */ dl_png_read_info (png_ptr, info_ptr); /* IHDRチャンク読み込み */ dl_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); lp_image->image_size.x = width; lp_image->image_size.y = height; /* Interlace */ if (dl_png_set_interlace_handling (png_ptr) != 1) { PF_ERROR_HANDLER (NO_SUPPORT_ERROR, "\"Interlace\" is not supported."); return 1; } /* 色データを8bitに設定する */ if ((color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) || (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) || (dl_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))) dl_png_set_expand (png_ptr); if (bit_depth < 8) dl_png_set_packing (png_ptr); if (bit_depth == 16) dl_png_set_strip_16 (png_ptr); if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) dl_png_set_strip_alpha(png_ptr); /* カラー印刷の場合3byteBGRに、モノクロの場合1byteに設定する */ if (!strcmp (format, "MONO")) /* モノクロ */ { if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA || color_type == PNG_COLOR_TYPE_PALETTE) dl_png_set_rgb_to_gray (png_ptr, 1, 0.3, 0.59); width_byte = WIDTHBYTES(width * 8); line = DEFAULT_BUFFER_SIZE / width_byte; } else /* カラー */ { if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_PALETTE) dl_png_set_gray_to_rgb (png_ptr); width_byte = WIDTHBYTES(width * 24); line = DEFAULT_BUFFER_SIZE / width_byte; } /* 今までの設定を反映させる */ dl_png_read_update_info (png_ptr, info_ptr); /* ラスターデータ格納用bufferを一行単位で確保 DEFAULT_BUFFER_SIZEを越えない最大サイズを確保する */ rows = (UCHAR**) pf_mem_alloc (sizeof (png_bytep) * line); if (rows == NULL) { PF_ERROR_HANDLER (MEMORY_ERROR, NULL); return 1; } lp_image->rows = rows; line = (line > 0) ? line : 1; for (i = 0; i < line; i++) { rows[i] = pf_mem_alloc (width_byte); if (rows[i] == NULL) { PF_ERROR_HANDLER (MEMORY_ERROR, NULL); return 1; } } lp_image->num_line = line; return 0; } static BOOL load_image_out (LP_IMG_STRUCT lp_image, LP_MKC_STRUCT lp_mkcode) { LIBPRT_BAND prt_band; LIBPRT_ATBMP_BAND atbmp_band; long h_ofs; HANDLE prt_handle = lp_mkcode->prt_handle; UCHAR *raster, *atbmp_raster; void* func; long h_prt_count, h_img_count; double h_mag; int atflag = 0; conf_print_image (lp_mkcode->lp_prtinfo, lp_image); if (atbmp_check ()) { if (atbmp_page_init (lp_image->image_size.x, lp_image->image_size.y)) { PF_ERROR_HANDLER (ATTRIBUTE_ERROR, NULL); return 1; } func = (void *)dlsym (lp_mkcode->lib_handle, DLL_BAND_OUT_AT); prt_band.lp_atbmp_band = & atbmp_band; atflag = 1; } else { func = (void *)dlsym (lp_mkcode->lib_handle, DLL_BAND_OUT); prt_band.lp_atbmp_band = NULL; } if (set_band_param (&prt_band, lp_image)) return 1; if (func == NULL) { PF_ERROR_HANDLER (DLL_ERROR, (char*)dlerror ()); return 1; } raster = (UCHAR*)pf_mem_alloc (prt_band.width_bytes + 3); if (!raster) { PF_ERROR_HANDLER (MEMORY_ERROR, NULL); return 1; } memset ((UCHAR*)raster, 0xff, prt_band.width_bytes + 3); atbmp_raster = NULL; if (atflag) { atbmp_raster = (UCHAR*)pf_mem_alloc (atbmp_band.width_bytes + 3); if (!atbmp_raster) { PF_ERROR_HANDLER (MEMORY_ERROR, NULL); return 1; } } h_prt_count = lp_image->print_size.y + lp_image->negative_margin.y; h_img_count = 0; h_mag = lp_image->magnify.y; for (h_ofs = 0; h_prt_count > 0; h_ofs ++) { UCHAR *image, *atbmp; /* imageの取得 */ image = read_raster_image (lp_image); if (!image) { PF_ERROR_HANDLER (UNEXPECTED_ERROR, NULL); return 1; } /* 横方向 */ set_raster (raster, image, lp_image->print_size.x, lp_image->negative_margin.x, lp_image->magnify.x, lp_image->byte_p_pixel); if (atflag) { atbmp = atbmp_read_attribute (); if (!atbmp) { PF_ERROR_HANDLER (ATTRIBUTE_ERROR, NULL); return 1; } set_raster (atbmp_raster, atbmp, lp_image->print_size.x, lp_image->negative_margin.x, lp_image->magnify.x, 1); } /* 縦方向 */ while (h_prt_count > 0 && write_judge (h_img_count, h_ofs, h_mag)) { if (h_prt_count <= lp_image->print_size.y) { if (band_flush (func, prt_handle, &prt_band, raster, atbmp_raster, 0)) { PF_ERROR_HANDLER (LIBPRT_ERROR, lp_mkcode->libprt_path); return 1; } } h_img_count ++; h_prt_count --; } } if (band_flush (func, prt_handle, &prt_band, NULL, NULL, 1)) { PF_ERROR_HANDLER (LIBPRT_ERROR, lp_mkcode->libprt_path); return 1; } seek_image (lp_image); atbmp_seek (); free_band_param (&prt_band); lp_mkcode->conv_status = CONV_STATUS_BAND_OUT; return 0; } static UCHAR* read_raster_image (LP_IMG_STRUCT lp_image) { long read_count = lp_image->read_line; int line_ofs; if (lp_image->read_line >= lp_image->image_size.y) return NULL; if (read_count == 0 || read_count % lp_image->num_line == 0) { /* pngからデータを読み込み、最初のラスターへのポインタを返す */ png_structp png_ptr = (png_structp)lp_image->png_ptr; long line; /* 読み込む(読み込める)ラスター数を決定 */ if (lp_image->num_line + read_count < lp_image->image_size.y) line = lp_image->num_line; else line = lp_image->image_size.y - read_count; dl_png_read_rows (png_ptr, lp_image->rows, NULL, line); line_ofs = 0; } else { /* 既に読み込んであるラスターへのポインタを返す */ line_ofs = read_count % lp_image->num_line; } lp_image->read_line ++; return lp_image->rows[line_ofs]; } static void seek_image (LP_IMG_STRUCT lp_image) { long line_number = lp_image->image_size.y - lp_image->read_line; long i; for (i = 0; i < line_number; i ++) { read_raster_image (lp_image); } return; } static void conf_print_image (LP_PRT_STRUCT lp_prtinfo, LP_IMG_STRUCT lp_image) { long positive_margin_x, positive_margin_y; /* 1pixel当りに必要なbyte数 */ if (strcmp (lp_prtinfo->ink, "COLOR")) { /* monochrome */ lp_image->byte_p_pixel = 1; } else { /* color */ lp_image->byte_p_pixel = 3; } if (lp_prtinfo->fit_page) { lp_image->negative_margin.x = 0; lp_image->negative_margin.y = 0; positive_margin_x = 0; positive_margin_y = 0; lp_image->magnify.x = (double)lp_prtinfo->paper_area.x / (double)lp_image->image_size.x; lp_image->magnify.y = (double)lp_prtinfo->paper_area.y / (double)lp_image->image_size.y; if (lp_image->magnify.x < lp_image->magnify.y) { lp_image->magnify.y = lp_image->magnify.x; /* positive_margin_y = (long)(((double)lp_prtinfo->paper_area.y - (double)lp_image->image_size.y * lp_image->magnify.x) / 2); */ } else { lp_image->magnify.x = lp_image->magnify.y; /* positive_margin_x = (long)(((double)lp_prtinfo->paper_area.x - (double)lp_image->image_size.x * lp_image->magnify.y) / 2); */ } } else { /* マージンの設定 */ if (lp_prtinfo->margin.x < lp_prtinfo->default_margin.x) { lp_image->negative_margin.x = fabs ((double)lp_prtinfo->margin.x - lp_prtinfo->default_margin.x); positive_margin_x = 0; } else { lp_image->negative_margin.x = 0; positive_margin_x = lp_prtinfo->margin.x - lp_prtinfo->default_margin.x; } if (lp_prtinfo->margin.y < lp_prtinfo->default_margin.y) { lp_image->negative_margin.y = fabs ((double)lp_prtinfo->margin.y - lp_prtinfo->default_margin.y); positive_margin_y = 0; } else { lp_image->negative_margin.y = 0; positive_margin_y = lp_prtinfo->margin.y - lp_prtinfo->default_margin.y; } /* 拡大/縮小 */ lp_image->magnify.x = (double)lp_prtinfo->ratio.x / 100.0; lp_image->magnify.y = (double)lp_prtinfo->ratio.y / 100.0; } if (lp_prtinfo->bin_id[0] == 'T') /* trim */ { double t_mag; double ty_mag; if (!strcmp (lp_prtinfo->bin_id, "TROLL") || lp_prtinfo->auto_cut[0] != '2') { lp_prtinfo->paper_area.y += lp_prtinfo->default_margin.y * 2; lp_image->negative_margin.y += lp_prtinfo->default_margin.y; } t_mag = (double)lp_prtinfo->paper_area.x / lp_prtinfo->paper_size.x; ty_mag = (double)lp_prtinfo->paper_area.y / lp_prtinfo->paper_size.y; t_mag = (t_mag > ty_mag) ? t_mag : ty_mag; lp_image->magnify.x *= t_mag; lp_image->magnify.y *= t_mag; } /* 印刷領域 */ if((lp_prtinfo->paper_area.x - positive_margin_x) < ((lp_image->image_size.x - lp_image->negative_margin.x) * lp_image->magnify.x)) { lp_image->print_size.x = lp_prtinfo->paper_area.x - positive_margin_x; } else { lp_image->print_size.x = (lp_image->image_size.x * lp_image->magnify.x) - lp_image->negative_margin.x; } if (lp_image->print_size.x % 2) lp_image->print_size.x--; if((lp_prtinfo->paper_area.y - positive_margin_y) < ((lp_image->image_size.y - lp_image->negative_margin.y) * lp_image->magnify.y)) { lp_image->print_size.y = lp_prtinfo->paper_area.y - positive_margin_y; } else { lp_image->print_size.y = (lp_image->image_size.y * lp_image->magnify.y) - lp_image->negative_margin.y; } lp_image->read_line = 0; } static void set_init_param (LP_LIBPRT_INIT lp_prt_init, LP_PRT_STRUCT lp_prtinfo, FILE* output) { lp_prt_init->output = output; lp_prt_init->paper = lp_prtinfo->paper; lp_prt_init->format = lp_prtinfo->ink; lp_prt_init->resol = lp_prtinfo->src_resol; lp_prt_init->high_speed = lp_prtinfo->high_speed; lp_prt_init->mw_type = lp_prtinfo->mw_type; lp_prt_init->bin_id = lp_prtinfo->bin_id; lp_prt_init->media_type = lp_prtinfo->media_type; lp_prt_init->qlevel = lp_prtinfo->qlevel; lp_prt_init->paper_size.x = lp_prtinfo->paper_size.x; lp_prt_init->paper_size.y = lp_prtinfo->paper_size.y; lp_prt_init->paper_area.x = (lp_prtinfo->margin.x < lp_prtinfo->default_margin.x) ? lp_prtinfo->paper_area.x : lp_prtinfo->paper_area.x - lp_prtinfo->margin.x + lp_prtinfo->default_margin.x; lp_prt_init->paper_area.y = (lp_prtinfo->margin.y < lp_prtinfo->default_margin.y) ? lp_prtinfo->paper_area.y : lp_prtinfo->paper_area.y - lp_prtinfo->margin.y + lp_prtinfo->default_margin.y; lp_prt_init->margin.x = lp_prtinfo->margin.x; lp_prt_init->margin.y = lp_prtinfo->margin.y; lp_prt_init->inkset = lp_prtinfo->inkset; lp_prt_init->auto_cut = lp_prtinfo->auto_cut; return; } static void set_page_param (LP_LIBPRT_PAGE lp_prt_page, LP_PRT_STRUCT lp_prtinfo) { lp_prt_page->color_mode = lp_prtinfo->color_mode; lp_prt_page->halftone_type = lp_prtinfo->halftone_type; lp_prt_page->brightness = lp_prtinfo->brightness; lp_prt_page->contrast = lp_prtinfo->contrast; lp_prt_page->saturation = lp_prtinfo->saturation; lp_prt_page->r_strength = lp_prtinfo->r_strength; lp_prt_page->g_strength = lp_prtinfo->g_strength; lp_prt_page->b_strength = lp_prtinfo->b_strength; return; } static BOOL set_band_param (LP_LIBPRT_BAND lp_prt_band, LP_IMG_STRUCT lp_image) { UCHAR* ex_raster; UCHAR* ex_atbmp_raster; long width_pixel; long width_bytes; long width_atbmp_bytes; width_pixel = lp_image->print_size.x; width_bytes = WIDTHBYTES(width_pixel * lp_image->byte_p_pixel * 8); width_atbmp_bytes = WIDTHBYTES(width_pixel * 8); ex_raster = (UCHAR*)pf_mem_alloc (width_bytes * 2); if (!ex_raster) { PF_ERROR_HANDLER (MEMORY_ERROR, NULL); return 1; } lp_prt_band->width_pixel = width_pixel; lp_prt_band->width_bytes = width_bytes; lp_prt_band->byte_data = ex_raster; if (lp_prt_band->lp_atbmp_band) { ex_atbmp_raster = (UCHAR*)pf_mem_alloc (width_atbmp_bytes * 2); if (!ex_atbmp_raster) { PF_ERROR_HANDLER (MEMORY_ERROR, NULL); return 1; } lp_prt_band->lp_atbmp_band->width_bytes = width_atbmp_bytes; lp_prt_band->lp_atbmp_band->byte_data = ex_atbmp_raster; } return 0; } static void free_band_param (LP_LIBPRT_BAND lp_prt_band) { if (lp_prt_band->byte_data != NULL) pf_mem_free (lp_prt_band->byte_data); return; } static BOOL write_judge (long count, long point, double mag) { long mag_count = floor ((point + 1) * mag); long now_count = count + 1; if (mag_count < now_count) return 0; /* 書き込み不許可 */ /* 書き込み許可 */ return 1; } #ifdef _V1_SUPPORT /* ESC/Pコードを読み飛ばす これは,v1との互換の為に存在し、v2では削除予定 */ static BOOL escp_through (FILE* infp, FILE* outfp, char* rbuf, int rnum) { char escp_head[] = "REMOTE1"; char buffer[DEFAULT_BUFFER_SIZE]; long numbuf = (long)rnum; long i; if (rbuf == NULL || rnum == 0) return 1; memcpy (buffer, rbuf, rnum); numbuf += fread (buffer + rnum, sizeof (char), DEFAULT_BUFFER_SIZE - rnum, infp); if ( numbuf < strlen (escp_head)) return 1; for (i = 0; i < numbuf - strlen (escp_head); i++) { if (!strncmp (buffer + i, escp_head, strlen (escp_head))) { fwrite (buffer, sizeof (char), numbuf, outfp); while ((numbuf = fread (buffer, sizeof (char), DEFAULT_BUFFER_SIZE, infp)) != 0) { fwrite (buffer, sizeof (char), numbuf, outfp); fflush (outfp); } if (numbuf) fwrite (buffer, sizeof (char), numbuf, outfp ); return -1; } } return 1; } #endif /* _V1_SUPPORT */ /* 2 line 渡し用の flag */ BOOL _2_Line_Flag; static BOOL band_flush (void* func, HANDLE prt_handle, LP_LIBPRT_BAND lp_prt_band, UCHAR *raster, UCHAR *atbmp_raster, BOOL flush_flag) { UCHAR *target_line; UCHAR *target_atbmp_line; LP_LIBPRT_ATBMP_BAND lp_atbmp_band = lp_prt_band->lp_atbmp_band; if (flush_flag) { if (!_2_Line_Flag) return 0; lp_prt_band->line_number = 1; } else { lp_prt_band->line_number = 2; if (_2_Line_Flag) target_line = lp_prt_band->byte_data + lp_prt_band->width_bytes; else target_line = lp_prt_band->byte_data; memcpy (target_line, raster, lp_prt_band->width_bytes); if (atbmp_raster) { if (_2_Line_Flag) target_atbmp_line = lp_atbmp_band->byte_data + lp_atbmp_band->width_bytes; else target_atbmp_line = lp_atbmp_band->byte_data; memcpy (target_atbmp_line, atbmp_raster, lp_atbmp_band->width_bytes); } } if (_2_Line_Flag) { if (atbmp_raster) { if ((*(OUT_AT_FUNC)func) (prt_handle, lp_prt_band)) return 1; } else { if ((*(OUT_FUNC)func) (prt_handle, lp_prt_band)) return 1; } } _2_Line_Flag ^= 1; return 0; } static void set_raster (UCHAR* raster, UCHAR* image_band, int size, int negative, double mag, int bpp) { int w_prt_count = size + negative; double w_mag = mag; int w_img_count = 0; int w_ofs; for (w_ofs = 0; w_prt_count > 0; w_ofs++) { while (w_prt_count > 0 && write_judge (w_img_count, w_ofs, w_mag)) { int i; UCHAR* to_band; if (w_prt_count <= size) { to_band = &(raster[(w_img_count - negative) * bpp]); for (i = 0; i < bpp; i++) to_band[i] = image_band[w_ofs * bpp + i]; } w_img_count ++; w_prt_count --; } } return; }