1 /*$
2  Copyright (C) 2013-2020 Azel.
3 
4  This file is part of AzPainter.
5 
6  AzPainter is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  AzPainter is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 $*/
19 
20 /*****************************************
21  * GIF 保存
22  *****************************************/
23 
24 #include <stdio.h>
25 
26 #include "mDef.h"
27 #include "mSaveImage.h"
28 #include "mGIFEncode.h"
29 
30 
31 //--------------------
32 
33 typedef struct
34 {
35 	mSaveImage *param;
36 
37 	mGIFEncode *gifenc;
38 	uint8_t *rowbuf,
39 		*palbuf;
40 
41 	int transparent;
42 }SAVEGIF;
43 
44 //--------------------
45 
46 
47 /** 初期化 */
48 
_init(SAVEGIF * p,mSaveImage * param)49 static int _init(SAVEGIF *p,mSaveImage *param)
50 {
51 	mGIFEncodeGlobalInfo global;
52 	mGIFEncodeImage img;
53 	int ret;
54 
55 	//パレット
56 
57 	p->palbuf = mSaveImage_convertPalette_RGB(param);
58 	if(!p->palbuf) return MSAVEIMAGE_ERR_ALLOC;
59 
60 	//GIF エンコーダ作成
61 
62 	global.width = param->width;
63 	global.height = param->height;
64 	global.bkgnd_index = 0;
65 	global.bits = mGIFEncode_colnumToBits(param->palette_num);
66 	global.palette_buf = p->palbuf;
67 	global.palette_num = param->palette_num;
68 
69 	p->gifenc = mGIFEncode_create(&global);
70 	if(!p->gifenc) return MSAVEIMAGE_ERR_ALLOC;
71 
72 	//開く
73 
74 	switch(param->output.type)
75 	{
76 		case MSAVEIMAGE_OUTPUT_TYPE_PATH:
77 			if(!mGIFEncode_open_filename(p->gifenc, param->output.filename))
78 				return MSAVEIMAGE_ERR_OPENFILE;
79 			break;
80 		case MSAVEIMAGE_OUTPUT_TYPE_STDIO:
81 			mGIFEncode_open_stdio(p->gifenc, param->output.fp);
82 			break;
83 	}
84 
85 	//ヘッダ
86 
87 	mGIFEncode_writeHeader(p->gifenc);
88 
89 	//設定
90 
91 	p->transparent = -1;
92 
93 	if((ret = (param->set_option)(param)))
94 		return ret;
95 
96 	//画像制御ブロック (透過色)
97 
98 	if(p->transparent >= 0)
99 		mGIFEncode_writeGrpCtrl(p->gifenc, p->transparent, 0, 0, FALSE);
100 
101 	//画像開始
102 
103 	img.offsetx = img.offsety = 0;
104 	img.width = param->width;
105 	img.height = param->height;
106 	img.palette_buf = NULL;
107 	img.palette_num = 0;
108 
109 	mGIFEncode_startImage(p->gifenc, &img);
110 
111 	//Y1行バッファ確保
112 
113 	p->rowbuf = (uint8_t *)mMalloc(param->width, FALSE);
114 	if(!p->rowbuf) return MSAVEIMAGE_ERR_ALLOC;
115 
116 	return 0;
117 }
118 
119 /** メイン処理 */
120 
_main_proc(SAVEGIF * p)121 static int _main_proc(SAVEGIF *p)
122 {
123 	mSaveImage *param = p->param;
124 	int ret,i;
125 
126 	//初期化
127 
128 	if((ret = _init(p, param)))
129 		return ret;
130 
131 	//画像
132 
133 	for(i = param->height; i > 0; i--)
134 	{
135 		//取得
136 
137 		ret = (param->send_row)(param, p->rowbuf, param->width);
138 		if(ret) return ret;
139 
140 		//書き込み
141 
142 		mGIFEncode_writeImage(p->gifenc, p->rowbuf, param->width);
143 	}
144 
145 	mGIFEncode_endImage(p->gifenc);
146 	mGIFEncode_writeEnd(p->gifenc);
147 
148 	return 0;
149 }
150 
151 
152 /**
153 
154 @ingroup saveimage
155 @{
156 
157 */
158 
159 
160 /** GIF ファイルに保存
161  *
162  * 入力データは 8bit パレットのみ。 */
163 
mSaveImageGIF(mSaveImage * param)164 mBool mSaveImageGIF(mSaveImage *param)
165 {
166 	SAVEGIF *p;
167 	int ret;
168 
169 	//確保
170 
171 	p = (SAVEGIF *)mMalloc(sizeof(SAVEGIF), TRUE);
172 	if(!p) return FALSE;
173 
174 	p->param = param;
175 	param->internal = p;
176 
177 	//処理
178 
179 	ret = _main_proc(p);
180 
181 	if(ret)
182 	{
183 		if(ret > 0)
184 			mSaveImage_setMessage_errno(param, ret);
185 	}
186 
187 	//解放
188 
189 	mGIFEncode_close(p->gifenc);
190 
191 	mFree(p->rowbuf);
192 	mFree(p->palbuf);
193 	mFree(p);
194 
195 	return (ret == 0);
196 }
197 
198 /** 透過色のインデックスをセット */
199 
mSaveImageGIF_setTransparent(mSaveImage * p,int index)200 void mSaveImageGIF_setTransparent(mSaveImage *p,int index)
201 {
202 	((SAVEGIF *)p->internal)->transparent = index;
203 }
204 
205 /* @} */
206