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 * mPSDSave
22 *****************************************/
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "mDef.h"
28 #include "mUtilStdio.h"
29 #include "mUtil.h"
30 #include "mUtilCharCode.h"
31
32 #include "mPSDSave.h"
33
34
35 //-------------------
36
37 typedef struct
38 {
39 long fpos_chinfo;
40 int left,top,width,height;
41 uint8_t channels;
42 }_layerinfo;
43
44
45 struct _mPSDSave
46 {
47 FILE *fp;
48 mPSDSaveInfo *info;
49
50 uint8_t *buf1, //作業用バッファ1
51 *buf2, //作業用バッファ2
52 *rowbuf, //チャンネルのY1行バッファ
53 *outbuf, //PackBits 書き込み用バッファ
54 //(無圧縮時は Unicode 名用バッファ)
55 compression; //0:無圧縮 1:PackBits
56
57 _layerinfo *curlinfo;
58
59 fpos_t fpos1,
60 fpos2;
61 uint32_t size1,
62 size2;
63 int layernum,
64 pitch,
65 cury,
66 curlayer,
67 curchannel,
68 outsize, //outbuf の現在の書き込みサイズ
69 layer_maxw, //レイヤイメージの最大サイズ
70 layer_maxh,
71 channel_id;
72 };
73
74 //-------------------
75
76 #define _OUTBUFSIZE (8 * 1024)
77 #define _MAX_UNICODE_NAME_LEN 256 //レイヤ名 Unicode の最大文字数
78
79 //-------------------
80
81
82
83 //========================
84 // PackBits 圧縮
85 //========================
86
87
88 /** outbuf のデータをファイルに書き込み */
89
_write_outbuf(mPSDSave * p)90 static void _write_outbuf(mPSDSave *p)
91 {
92 if(p->outsize)
93 {
94 fwrite(p->outbuf, 1, p->outsize, p->fp);
95 p->outsize = 0;
96 }
97 }
98
99 /** データ書き込み
100 *
101 * @param type 0:非連続 1:連続
102 * @return 書き込んだサイズ */
103
_packbits_write(mPSDSave * p,uint8_t type,uint8_t * buf,int cnt)104 static int _packbits_write(mPSDSave *p,uint8_t type,uint8_t *buf,int cnt)
105 {
106 int size,len;
107 uint8_t *pd;
108
109 //長さ
110
111 len = cnt - 1;
112 if(type) len = -len;
113
114 //データサイズ
115
116 size = 1 + ((type)? 1: cnt);
117
118 //バッファを超える場合はファイルに出力
119
120 if(p->outsize + size >= _OUTBUFSIZE)
121 _write_outbuf(p);
122
123 //バッファに追加
124
125 pd = p->outbuf + p->outsize;
126
127 *pd = (uint8_t)len;
128
129 if(type)
130 pd[1] = *buf;
131 else
132 memcpy(pd + 1, buf, cnt);
133
134 p->outsize += size;
135
136 return size;
137 }
138
139 /** PackBits 圧縮
140 *
141 * outbuf に圧縮データを書き込み、バッファがいっぱいになったらファイルへ書き込む。
142 *
143 * @return 圧縮サイズ */
144
_encode_packbits(mPSDSave * p,uint8_t * buf,int size)145 static int _encode_packbits(mPSDSave *p,uint8_t *buf,int size)
146 {
147 uint8_t *ps,*psend,*ps2,val;
148 int write = 0;
149
150 ps = buf;
151 psend = ps + size;
152
153 while(ps < psend)
154 {
155 if(ps == psend - 1 || *ps != ps[1])
156 {
157 //非連続データ (次の連続データが見つかるまで)
158
159 for(ps2 = ps; ps - ps2 < 128; ps++)
160 {
161 if(ps == psend - 1)
162 {
163 ps++;
164 break;
165 }
166 else if(*ps == ps[1])
167 break;
168 }
169
170 write += _packbits_write(p, 0, ps2, ps - ps2);
171 }
172 else
173 {
174 //連続データ
175
176 val = *ps;
177 ps2 = ps;
178
179 for(ps += 2; ps < psend && ps - ps2 < 128 && *ps == val; ps++);
180
181 write += _packbits_write(p, 1, ps2, ps - ps2);
182 }
183 }
184
185 return write;
186 }
187
188
189 //=========================
190 // sub
191 //=========================
192
193
194 /** Unicode レイヤ名を outbuf にセット
195 *
196 * NULL 文字は含まない。
197 * データは 4byte 境界。
198 *
199 * @return 文字数 */
200
_set_layername_unicode(mPSDSave * p,const char * name)201 static int _set_layername_unicode(mPSDSave *p,const char *name)
202 {
203 uint8_t *pd;
204 uint32_t c,c2;
205 int ret,len;
206
207 pd = p->outbuf;
208 len = 0;
209
210 while(*name && len < _MAX_UNICODE_NAME_LEN)
211 {
212 ret = mUTF8ToUCS4Char(name, -1, &c, &name);
213
214 if(ret < 0)
215 return 0;
216 else if(ret == 0)
217 {
218 if(c <= 0xffff)
219 {
220 pd[0] = c >> 8;
221 pd[1] = (uint8_t)c;
222 pd += 2;
223 len++;
224 }
225 else
226 {
227 c -= 0x10000;
228 c2 = c >> 16;
229
230 pd[0] = 0xd8 | (c2 >> 2);
231 pd[1] = ((c2 & 3) << 6) | ((c >> 10) & 63);
232 pd[2] = 0xdc | ((c >> 8) & 3);
233 pd[3] = (uint8_t)c;
234
235 pd += 4;
236 len += 2;
237 }
238 }
239 }
240
241 //余白追加 (4byte境界)
242
243 if(len & 1)
244 pd[0] = pd[1] = 0;
245
246 return len;
247 }
248
249
250 //=========================
251 // main
252 //=========================
253
254
255 /*******************//**
256
257 @defgroup psdsave mPSDSave
258 @brief PSD 書き込み
259
260 @ingroup group_image
261
262 @{
263 @file mPSDSave.h
264
265 @struct mPSDSaveInfo
266 @enum MPSD_COLMODE
267 @enum MPSD_BLENDMODE
268
269 ************************/
270
271
272 /** 閉じる */
273
mPSDSave_close(mPSDSave * p)274 void mPSDSave_close(mPSDSave *p)
275 {
276 if(p)
277 {
278 if(p->fp) fclose(p->fp);
279
280 mFree(p->buf1);
281 mFree(p->buf2);
282 mFree(p->rowbuf);
283 mFree(p->outbuf);
284
285 mFree(p);
286 }
287 }
288
289 /** ファイルから開く
290 *
291 * @param packbits PackBits 圧縮を行うか (FALSE で無圧縮) */
292
mPSDSave_openFile(const char * filename,mPSDSaveInfo * info,mBool packbits)293 mPSDSave *mPSDSave_openFile(const char *filename,mPSDSaveInfo *info,mBool packbits)
294 {
295 mPSDSave *p;
296 uint8_t dat[26];
297
298 //確保
299
300 p = (mPSDSave *)mMalloc(sizeof(mPSDSave), TRUE);
301 if(!p) return NULL;
302
303 p->info = info;
304 p->compression = (packbits != 0);
305
306 //PackBits 書き込み用バッファ
307 //(無圧縮時は Unicode 名用バッファ)
308
309 p->outbuf = (uint8_t *)mMalloc(
310 (packbits)? _OUTBUFSIZE: ((_MAX_UNICODE_NAME_LEN * 2 + 3) & ~3), FALSE);
311
312 if(!p->outbuf)
313 {
314 mPSDSave_close(p);
315 return NULL;
316 }
317
318 //ファイル開く
319
320 p->fp = mFILEopenUTF8(filename, "wb");
321 if(!p->fp)
322 {
323 mPSDSave_close(p);
324 return NULL;
325 }
326
327 //ファイルヘッダ書き込み
328
329 mSetBufBE_args(dat, "s24224422",
330 "8BPS",
331 1, //version
332 0, 0, //reversed
333 p->info->img_channels, p->info->height, p->info->width,
334 p->info->bits, p->info->colmode);
335
336 fwrite(dat, 1, 26, p->fp);
337
338 //カラーモードデータサイズ (0)
339
340 mFILEwriteZero(p->fp, 4);
341
342 return p;
343 }
344
345 /** イメージ書き込み先バッファ取得 */
346
mPSDSave_getLineImageBuf(mPSDSave * p)347 uint8_t *mPSDSave_getLineImageBuf(mPSDSave *p)
348 {
349 return p->rowbuf;
350 }
351
352
353 //=========================
354 // 画像リソースデータ
355 //=========================
356 /*
357 * fpos1 : 全体サイズ書き込み位置
358 * size1 : 全体サイズ
359 *
360 * 各データは 2byte 境界。
361 * 奇数の場合は、データサイズはそのままで、余白データを 1byte 追加。
362 */
363
364
365 /** 画像リソースデータ開始 */
366
mPSDSave_beginResource(mPSDSave * p)367 void mPSDSave_beginResource(mPSDSave *p)
368 {
369 //全体サイズ (仮)
370
371 fgetpos(p->fp, &p->fpos1);
372 mFILEwriteZero(p->fp, 4);
373
374 p->size1 = 0;
375 }
376
377 /** 画像リソースデータ終了 */
378
mPSDSave_endResource(mPSDSave * p)379 void mPSDSave_endResource(mPSDSave *p)
380 {
381 //データが空の場合、すでに仮サイズで 0 を書き込んでいるので、何もしない
382
383 if(p->size1)
384 {
385 fsetpos(p->fp, &p->fpos1);
386 mFILEwrite32BE(p->fp, p->size1);
387 fseek(p->fp, 0, SEEK_END);
388 }
389 }
390
391 /** 画像リソース:解像度を DPI 単位で書き込み */
392
mPSDSave_writeResource_resolution_dpi(mPSDSave * p,int dpi_horz,int dpi_vert)393 void mPSDSave_writeResource_resolution_dpi(mPSDSave *p,int dpi_horz,int dpi_vert)
394 {
395 uint8_t dat[28] = {
396 0x38,0x42,0x49,0x4d, //'8BIM'
397 0x03,0xed, //ID (0x03ed)
398 0x00,0x00, //name
399 0x00,0x00,0x00,0x10, //size
400 0x00,0x00,0x00,0x00, 0x00,0x01, 0x00,0x02, //H
401 0x00,0x00,0x00,0x00, 0x00,0x01, 0x00,0x02 //V
402
403 /* [4byte:16+16bit固定小数点] [2byte:1=pixel per inch] [2byte:2=cm] */
404 };
405
406 //固定小数点数の整数部分をセット
407
408 mSetBuf16BE(dat + 12, dpi_horz);
409 mSetBuf16BE(dat + 20, dpi_vert);
410
411 fwrite(dat, 1, 28, p->fp);
412
413 p->size1 += 28;
414 }
415
416 /** 画像リソース:カレントレイヤ番号を書き込み
417 *
418 * @param no 一番下のレイヤを 0 とする */
419
mPSDSave_writeResource_currentLayer(mPSDSave * p,int no)420 void mPSDSave_writeResource_currentLayer(mPSDSave *p,int no)
421 {
422 uint8_t dat[14] = {
423 0x38,0x42,0x49,0x4d, //'8BIM'
424 0x04,0x00, //ID (0x0400)
425 0x00,0x00, //name
426 0x00,0x00,0x00,0x02, //size
427 0x00,0x00
428 };
429
430 mSetBuf16BE(dat + 12, no);
431 fwrite(dat, 1, 14, p->fp);
432
433 p->size1 += 14;
434 }
435
436
437 //=============================
438 // 一枚絵イメージ
439 //=============================
440 /*
441 * fpos1 : Y圧縮サイズリスト書き込み位置
442 * buf1 : Y圧縮サイズリストバッファ
443 */
444
445
446 /** 一枚絵イメージ 書き込み開始
447 *
448 * レイヤデータ書き込み後。*/
449
mPSDSave_beginImage(mPSDSave * p)450 mBool mPSDSave_beginImage(mPSDSave *p)
451 {
452 int i,lsize;
453
454 //チャンネルのY1行サイズ
455
456 if(p->info->bits == 1)
457 p->pitch = (p->info->width + 7) >> 3;
458 else
459 p->pitch = p->info->width;
460
461 //Y1行バッファ
462
463 p->rowbuf = (uint8_t *)mMalloc(p->pitch, FALSE);
464 if(!p->rowbuf) return FALSE;
465
466 //PackBits Y圧縮サイズリストバッファ
467
468 if(p->compression)
469 {
470 lsize = p->info->height * 2;
471
472 p->buf1 = (uint8_t *)mMalloc(lsize, TRUE);
473 if(!p->buf1) return FALSE;
474 }
475
476 //圧縮タイプ
477
478 mFILEwrite16BE(p->fp, p->compression);
479
480 //Y圧縮サイズリストを仮出力
481
482 if(p->compression)
483 {
484 fgetpos(p->fp, &p->fpos1);
485
486 for(i = p->info->img_channels; i > 0; i--)
487 fwrite(p->buf1, 1, lsize, p->fp);
488 }
489
490 return TRUE;
491 }
492
493 /** 一枚絵イメージ、各チャンネルの書き込み開始 */
494
mPSDSave_beginImageChannel(mPSDSave * p)495 void mPSDSave_beginImageChannel(mPSDSave *p)
496 {
497 p->cury = 0;
498 p->outsize = 0;
499 }
500
501 /** 一枚絵イメージ、各チャンネルのY1行イメージ書き込み
502 *
503 * mPSDSave_getLineImageBuf() で取得したバッファに書き込んでおく。 */
504
mPSDSave_writeImageChannelLine(mPSDSave * p)505 void mPSDSave_writeImageChannelLine(mPSDSave *p)
506 {
507 int size;
508
509 if(p->cury < p->info->height)
510 {
511 if(p->compression == 0)
512 {
513 //無圧縮
514
515 fwrite(p->rowbuf, 1, p->pitch, p->fp);
516 }
517 else
518 {
519 //PackBits
520
521 size = _encode_packbits(p, p->rowbuf, p->pitch);
522
523 mSetBuf16BE(p->buf1 + (p->cury << 1), size);
524 }
525
526 p->cury++;
527 }
528 }
529
530 /** 一枚絵イメージ、各チャンネルの書き込み終了 */
531
mPSDSave_endImageChannel(mPSDSave * p)532 void mPSDSave_endImageChannel(mPSDSave *p)
533 {
534 //バッファの残りデータを出力
535
536 _write_outbuf(p);
537
538 //Y圧縮サイズリスト
539
540 if(p->compression)
541 {
542 fsetpos(p->fp, &p->fpos1);
543 fwrite(p->buf1, 1, p->info->height * 2, p->fp);
544
545 //次の書き込み位置
546
547 fgetpos(p->fp, &p->fpos1);
548 fseek(p->fp, 0, SEEK_END);
549 }
550 }
551
552
553 //=============================
554 // レイヤ
555 //=============================
556 /*
557 * fpos1 : 全体サイズ書き込み位置
558 * fpos2 : 各チャンネルのY圧縮サイズリスト書き込み位置
559 * buf1 : 全レイヤの情報データ記録用
560 * buf2 : Y圧縮サイズリストバッファ
561 * size1 : 各チャンネルの圧縮サイズ
562 * size2 : レイヤデータ全体のサイズ
563 */
564
565
566 /** レイヤなしの場合、一枚絵イメージの前に書き込み */
567
mPSDSave_writeLayerNone(mPSDSave * p)568 void mPSDSave_writeLayerNone(mPSDSave *p)
569 {
570 mFILEwrite32BE(p->fp, 0);
571 }
572
573 /** レイヤ書き込み開始
574 *
575 * @param num レイヤ数 */
576
mPSDSave_beginLayer(mPSDSave * p,int num)577 mBool mPSDSave_beginLayer(mPSDSave *p,int num)
578 {
579 p->layernum = num;
580 p->curlayer = 0;
581 p->layer_maxw = p->layer_maxh = 0;
582 p->size2 = 2; //2 = レイヤ数
583
584 //レイヤ情報バッファ確保
585
586 p->buf1 = (uint8_t *)mMalloc(sizeof(_layerinfo) * num, FALSE);
587 if(!p->buf1) return FALSE;
588
589 p->curlinfo = (_layerinfo *)p->buf1;
590
591 //書き込み
592
593 fgetpos(p->fp, &p->fpos1);
594
595 mFILEwriteZero(p->fp, 8); //全体サイズ(4) + 内部全体サイズ(4)
596 mFILEwrite16BE(p->fp, num); //レイヤ数
597
598 return TRUE;
599 }
600
601 /** レイヤ情報書き込み
602 *
603 * mPSDSave_beginLayer() 後、一番下のレイヤを先頭として、全レイヤ分を書き込む。 */
604
mPSDSave_writeLayerInfo(mPSDSave * p,mPSDSaveLayerInfo * info)605 void mPSDSave_writeLayerInfo(mPSDSave *p,mPSDSaveLayerInfo *info)
606 {
607 FILE *fp = p->fp;
608 _layerinfo *winfo;
609 int i,name_len,name_len4,name_uni_len,name_uni_size4,exsize;
610
611 if(p->curlayer >= p->layernum) return;
612
613 //必要な情報を保存
614
615 winfo = p->curlinfo;
616
617 winfo->left = info->left;
618 winfo->top = info->top;
619 winfo->width = info->right - info->left;
620 winfo->height = info->bottom - info->top;
621
622 //イメージの最大サイズを記録しておく
623
624 if(p->layer_maxw < winfo->width) p->layer_maxw = winfo->width;
625 if(p->layer_maxh < winfo->height) p->layer_maxh = winfo->height;
626
627 //------ 基本データ書き込み
628
629 //範囲
630
631 mFILEwrite32BE(fp, info->top);
632 mFILEwrite32BE(fp, info->left);
633 mFILEwrite32BE(fp, info->bottom);
634 mFILEwrite32BE(fp, info->right);
635
636 //チャンネル数
637
638 mFILEwrite16BE(fp, info->channels);
639
640 //チャンネルデータ
641
642 winfo->fpos_chinfo = ftell(fp);
643
644 for(i = 0; i < info->channels; i++)
645 {
646 //ID (仮)
647
648 mFILEwrite16BE(fp, 0);
649
650 //データサイズ (仮)
651 /* 範囲なしの場合、圧縮フラグ[2byte]のみなので、2 をセットしておく */
652
653 mFILEwrite32BE(fp, 2);
654 }
655
656 //8BIM
657
658 fputs("8BIM", fp);
659
660 //合成モード
661
662 mFILEwrite32BE(fp, info->blendmode);
663
664 //不透明度
665
666 mFILEwriteByte(fp, info->opacity);
667
668 //clip
669
670 mFILEwriteByte(fp, 0);
671
672 //フラグ [0bit:透明色保護 1bit:非表示]
673
674 mFILEwriteByte(fp, (info->hide)? 2: 0);
675
676 //0
677
678 mFILEwriteByte(fp, 0);
679
680 //-------- 拡張データ
681
682 /* 4byte: 以下の拡張データサイズ
683 * 4byte: レイヤマスクデータサイズ
684 * 4byte: 合成データサイズ
685 * パスカル文字列: レイヤ名 [!]4byte境界(長さのバイトも含む)
686 * 8BIM + key のデータが並ぶ
687 */
688
689 name_len = name_uni_len = 0;
690 exsize = 0;
691
692 //レイヤ名長さ
693
694 if(info->name)
695 {
696 name_len = strlen(info->name);
697 if(name_len > 255) name_len = 255;
698 }
699
700 name_len4 = (name_len + 1 + 3) & ~3;
701
702 //Unicode レイヤ名 (outbuf にセット)
703
704 if(name_len)
705 {
706 name_uni_len = _set_layername_unicode(p, info->name);
707
708 name_uni_size4 = (name_uni_len * 2 + 3) & ~3;
709 exsize += 8 + 4 + 4 + name_uni_size4;
710 }
711
712 //****
713
714 //拡張データサイズ
715
716 mFILEwrite32BE(fp, 8 + name_len4 + exsize);
717
718 //レイヤマスクデータサイズ + 合成データサイズ
719
720 mFILEwriteZero(fp, 8);
721
722 //レイヤ名
723
724 mFILEwriteByte(fp, name_len);
725 fwrite(info->name, 1, name_len, fp);
726 mFILEwriteZero(fp, name_len4 - name_len - 1); //余白
727
728 //レイヤ名 (Unicode)
729
730 if(name_uni_len)
731 {
732 fputs("8BIMluni", fp);
733 mFILEwrite32BE(fp, 4 + name_uni_size4);
734 mFILEwrite32BE(fp, name_uni_len);
735 fwrite(p->outbuf, 1, name_uni_size4, fp);
736 }
737
738 //次へ
739
740 p->curlayer++;
741 p->curlinfo++;
742 p->size2 += 66 + name_len4 + exsize;
743 }
744
745 /** レイヤ情報書き込み終了
746 *
747 * イメージ書き込みの準備を行う。 */
748
mPSDSave_endLayerInfo(mPSDSave * p)749 mBool mPSDSave_endLayerInfo(mPSDSave *p)
750 {
751 p->curlayer = 0;
752 p->curlinfo = (_layerinfo *)p->buf1;
753
754 //バッファ確保
755
756 p->rowbuf = (uint8_t *)mMalloc(p->layer_maxw, FALSE);
757 if(!p->rowbuf) return FALSE;
758
759 if(p->compression)
760 {
761 p->buf2 = (uint8_t *)mMalloc(p->layer_maxh * 2, FALSE);
762 if(!p->buf2) return FALSE;
763 }
764
765 return TRUE;
766 }
767
768 /** 各レイヤのイメージ書き込み開始
769 *
770 * 空イメージの場合は、イメージデータが書き込まれるで、チャンネルイメージを描画する必要はない。
771 *
772 * @param box イメージ範囲が入る (NULL で取得しない)
773 * @return イメージ範囲があるか (FALSE で空イメージ) */
774
mPSDSave_beginLayerImage(mPSDSave * p,mBox * box)775 mBool mPSDSave_beginLayerImage(mPSDSave *p,mBox *box)
776 {
777 _layerinfo *winfo;
778
779 if(p->curlayer >= p->layernum) return FALSE;
780
781 p->curchannel = 0;
782
783 winfo = p->curlinfo;
784
785 //イメージ範囲
786
787 if(box)
788 {
789 box->x = winfo->left;
790 box->y = winfo->top;
791 box->w = winfo->width;
792 box->h = winfo->height;
793 }
794
795 //空かどうか
796
797 if(winfo->width && winfo->height)
798 return TRUE;
799 else
800 {
801 //空ならイメージデータ書き込み
802 /* 圧縮フラグ(2byte) = 0:無圧縮 x 4 ch */
803
804 mFILEwriteZero(p->fp, 2 * 4);
805
806 p->size2 += 8;
807
808 return FALSE;
809 }
810 }
811
812 /** レイヤの各チャンネル書き込み開始 */
813
mPSDSave_beginLayerImageChannel(mPSDSave * p,int channel_id)814 void mPSDSave_beginLayerImageChannel(mPSDSave *p,int channel_id)
815 {
816 p->channel_id = channel_id;
817 p->cury = 0;
818 p->outsize = 0;
819 p->size1 = 2;
820
821 //圧縮フラグ
822
823 mFILEwrite16BE(p->fp, p->compression);
824
825 //Y圧縮サイズリスト (仮)
826
827 if(p->compression)
828 {
829 fgetpos(p->fp, &p->fpos2);
830
831 fwrite(p->buf2, 1, p->curlinfo->height * 2, p->fp);
832
833 p->size1 += p->curlinfo->height * 2;
834 }
835 }
836
837 /** レイヤイメージの最大幅取得 */
838
mPSDSave_getLayerImageMaxWidth(mPSDSave * p)839 int mPSDSave_getLayerImageMaxWidth(mPSDSave *p)
840 {
841 return p->layer_maxw;
842 }
843
844 /** レイヤのチャンネルイメージ Y1行を出力 */
845
mPSDSave_writeLayerImageChannelLine(mPSDSave * p)846 void mPSDSave_writeLayerImageChannelLine(mPSDSave *p)
847 {
848 int size;
849
850 if(p->cury < p->curlinfo->height)
851 {
852 if(p->compression == 0)
853 {
854 //無圧縮
855
856 fwrite(p->rowbuf, 1, p->curlinfo->width, p->fp);
857
858 size = p->curlinfo->width;
859 }
860 else
861 {
862 //PackBits
863
864 size = _encode_packbits(p, p->rowbuf, p->curlinfo->width);
865
866 mSetBuf16BE(p->buf2 + (p->cury << 1), size);
867 }
868
869 p->cury++;
870 p->size1 += size;
871 }
872 }
873
874 /** レイヤのチャンネルイメージ書き込み終了 */
875
mPSDSave_endLayerImageChannel(mPSDSave * p)876 void mPSDSave_endLayerImageChannel(mPSDSave *p)
877 {
878 //PackBits 残りを出力
879
880 _write_outbuf(p);
881
882 //チャンネル情報を書き込み
883
884 fseek(p->fp, p->curlinfo->fpos_chinfo + p->curchannel * 6, SEEK_SET);
885
886 mFILEwrite16BE(p->fp, p->channel_id);
887 mFILEwrite32BE(p->fp, p->size1);
888
889 //Y圧縮サイズリスト書き込み
890
891 if(p->compression)
892 {
893 fsetpos(p->fp, &p->fpos2);
894 fwrite(p->buf2, 1, p->curlinfo->height * 2, p->fp);
895 }
896
897 fseek(p->fp, 0, SEEK_END);
898
899 //
900
901 p->curchannel++;
902 p->size2 += p->size1;
903 }
904
905 /** 各レイヤイメージ書き込み終了 */
906
mPSDSave_endLayerImage(mPSDSave * p)907 void mPSDSave_endLayerImage(mPSDSave *p)
908 {
909 p->curlayer++;
910 p->curlinfo++;
911 }
912
913 /** レイヤの書き込み終了 */
914
mPSDSave_endLayer(mPSDSave * p)915 void mPSDSave_endLayer(mPSDSave *p)
916 {
917 //2byte 境界
918
919 if(p->size2 & 1)
920 {
921 mFILEwriteByte(p->fp, 0);
922 p->size2++;
923 }
924
925 //全体サイズ書き込み
926
927 fsetpos(p->fp, &p->fpos1);
928
929 mFILEwrite32BE(p->fp, p->size2 + 4);
930 mFILEwrite32BE(p->fp, p->size2);
931
932 fseek(p->fp, 0, SEEK_END);
933
934 //バッファ解放
935
936 mFree(p->buf1);
937 mFree(p->buf2);
938 mFree(p->rowbuf);
939
940 p->buf1 = p->buf2 = p->rowbuf = NULL;
941 }
942
943 /* @} */
944