1 /*$
2 Copyright (C) 2016-2020 Azel.
3
4 This file is part of AzPainterB.
5
6 AzPainterB 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 AzPainterB 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 * PSD 読み書き
22 *****************************************/
23
24 #include <string.h>
25
26 #include "mDef.h"
27 #include "mPopupProgress.h"
28 #include "mPSDLoad.h"
29 #include "mPSDSave.h"
30 #include "mUtilFile.h"
31
32 #include "defMacros.h"
33 #include "defDraw.h"
34 #include "defConfig.h"
35
36 #include "TileImage.h"
37 #include "LayerList.h"
38 #include "LayerItem.h"
39 #include "ImageBuf24.h"
40
41 #include "draw_main.h"
42
43
44 //--------------------
45
46 enum
47 {
48 _TYPE_RGB = 1,
49 _TYPE_GRAY,
50 _TYPE_MONO
51 };
52
53 #define _TOGRAY(r,g,b) ((r * 77 + g * 150 + b * 29) >> 8)
54
55 //--------------------
56
57 static const uint32_t g_blendmode[] = {
58 MPSD_BLENDMODE_NORMAL, MPSD_BLENDMODE_MULTIPLY, MPSD_BLENDMODE_LINEAR_DODGE,
59 MPSD_BLENDMODE_SUBTRACT, MPSD_BLENDMODE_SCREEN, MPSD_BLENDMODE_OVERLAY,
60 MPSD_BLENDMODE_HARD_LIGHT, MPSD_BLENDMODE_SOFT_LIGHT, MPSD_BLENDMODE_DODGE,
61 MPSD_BLENDMODE_BURN, MPSD_BLENDMODE_LINEAR_BURN, MPSD_BLENDMODE_VIVID_LIGHT,
62 MPSD_BLENDMODE_LINEAR_LIGHT, MPSD_BLENDMODE_PIN_LIGHT, MPSD_BLENDMODE_DARKEN,
63 MPSD_BLENDMODE_LIGHTEN, MPSD_BLENDMODE_DIFFERENCE, 0
64 };
65
66 //--------------------
67
68
69 //=============================
70 // 読み込み
71 //=============================
72
73
74 /** レイヤ読み込み - チャンネルを読み込み、バッファにセット */
75
_load_layer_image_channel(mPSDLoad * psd,mBox * boximg,mPopupProgress * prog,uint8_t * dstbuf)76 static mBool _load_layer_image_channel(mPSDLoad *psd,mBox *boximg,mPopupProgress *prog,uint8_t *dstbuf)
77 {
78 int i,w;
79 uint8_t *ps;
80
81 w = boximg->w;
82 ps = mPSDLoad_getLineImageBuf(psd);
83
84 for(i = boximg->h; i > 0; i--)
85 {
86 if(!mPSDLoad_readLayerImageChannelLine(psd))
87 return FALSE;
88
89 memcpy(dstbuf, ps, w);
90 dstbuf += w;
91
92 mPopupProgressThreadIncSubStep(prog);
93 }
94
95 return TRUE;
96 }
97
98 /** レイヤ読み込み - アルファ値読み込み
99 *
100 * @return FALSE 時は、psd->err にエラー番号を入れておく */
101
_load_layer_image_alpha(mPSDLoad * psd,TileImage * img,mPSDLoadLayerInfo * info,mPopupProgress * prog,uint8_t * buf)102 static mBool _load_layer_image_alpha(mPSDLoad *psd,
103 TileImage *img,mPSDLoadLayerInfo *info,mPopupProgress *prog,uint8_t *buf)
104 {
105 uint8_t *ps,*pd;
106 int ret,ix,iy;
107 mBox box;
108
109 box = info->box_img;
110
111 //アルファチャンネルを buf にセット
112
113 ret = mPSDLoad_beginLayerImageChannel(psd, MPSD_CHANNEL_ID_ALPHA);
114 if(!ret) return FALSE;
115
116 if(ret == -1)
117 {
118 //チャンネルがない場合はすべて不透明
119
120 memset(buf, 255, box.w * box.h);
121 mPopupProgressThreadAddPos(prog, 4);
122 }
123 else
124 {
125 //読み込み
126
127 mPopupProgressThreadBeginSubStep(prog, 4, box.h);
128
129 if(!_load_layer_image_channel(psd, &box, prog, buf))
130 return FALSE;
131 }
132
133 //レイヤマスクがある場合、アルファ値に適用
134
135 if(!(info->layermask_flags & MPSDLOAD_LAYERMASK_F_DISABLE))
136 {
137 ret = mPSDLoad_beginLayerImageChannel(psd, MPSD_CHANNEL_ID_MASK);
138 if(!ret) return FALSE;
139
140 if(ret != -1)
141 {
142 pd = buf;
143
144 for(iy = box.h; iy > 0; iy--)
145 {
146 if(!mPSDLoad_readLayerImageChannelLine_mask(psd))
147 return FALSE;
148
149 ps = mPSDLoad_getLineImageBuf(psd);
150
151 for(ix = box.w; ix > 0; ix--, ps++, pd++)
152 {
153 if(*pd > *ps) *pd = *ps;
154 }
155 }
156 }
157 }
158
159 //アルファ値セット
160
161 if(TileImage_setChannelImage(img, buf, 3, box.w, box.h, FALSE))
162 return TRUE;
163 else
164 {
165 psd->err = MPSDLOAD_ERR_ALLOC;
166 return FALSE;
167 }
168 }
169
170 /** レイヤ読み込み - イメージ */
171
_load_layer_image(DrawData * p,mPSDLoad * psd,mPopupProgress * prog)172 static int _load_layer_image(DrawData *p,mPSDLoad *psd,mPopupProgress *prog)
173 {
174 mPSDLoadLayerInfo info;
175 LayerItem *item;
176 TileImage *img;
177 uint8_t *allocbuf = NULL,*buf;
178 mSize size;
179 int i,chnum,ret;
180
181 chnum = (psd->colmode == MPSD_COLMODE_GRAYSCALE)? 1: 3;
182
183 //1チャンネル分のバッファ確保
184 //(blendimg のバッファで足りるならそちらを使う)
185
186 mPSDLoad_getLayerImageMaxSize(psd, &size);
187
188 if(size.w * size.h <= p->imgw * p->imgh * 3)
189 buf = (uint8_t *)p->blendimg->buf;
190 else
191 {
192 buf = allocbuf = (uint8_t *)mMalloc(size.w * size.h, FALSE);
193 if(!allocbuf) return MPSDLOAD_ERR_ALLOC;
194 }
195
196 //---- 各レイヤ読み込み
197 /* ファイルの格納順に読み込むので、
198 * 一覧上において下から順にイメージのあるレイヤを読み込み。 */
199
200 mPopupProgressThreadSetMax(prog,
201 LayerList_getNormalLayerNum(p->layerlist) * 16);
202
203 item = LayerList_getItem_bottomNormal(p->layerlist);
204
205 for(; item; item = LayerItem_getPrevNormal(item))
206 {
207 //読み込み開始
208
209 if(!mPSDLoad_beginLayerImage(psd, &info, TRUE))
210 {
211 //空イメージ
212
213 mPSDLoad_endLayerImage(psd);
214 mPopupProgressThreadAddPos(prog, 16);
215 continue;
216 }
217
218 img = item->img;
219
220 //A チャンネルを先に読み込み
221
222 if(!_load_layer_image_alpha(psd, img, &info, prog, buf))
223 goto ERR;
224
225 //色チャンネル読み込み
226
227 for(i = 0; i < chnum; i++)
228 {
229 //開始
230
231 ret = mPSDLoad_beginLayerImageChannel(psd, i);
232 if(!ret)
233 goto ERR;
234 else if(ret == -1)
235 {
236 mPopupProgressThreadAddPos(prog, 4);
237 continue;
238 }
239
240 //buf に読み込み
241
242 mPopupProgressThreadBeginSubStep(prog, (chnum == 1)? 12: 4, info.box_img.h);
243
244 if(!_load_layer_image_channel(psd, &info.box_img, prog, buf))
245 goto ERR;
246
247 //セット
248
249 TileImage_setChannelImage(img, buf, i,
250 info.box_img.w, info.box_img.h, (i == 0 && chnum == 1));
251 }
252
253 mPSDLoad_endLayerImage(psd);
254 }
255
256 mFree(allocbuf);
257
258 return MPSDLOAD_ERR_OK;
259
260 ERR:
261 mFree(allocbuf);
262 return psd->err;
263 }
264
265 /** レイヤ読み込み */
266
_load_from_layer(DrawData * p,mPSDLoad * psd,mPopupProgress * prog)267 static int _load_from_layer(DrawData *p,mPSDLoad *psd,mPopupProgress *prog)
268 {
269 mPSDLoadLayerInfo info;
270 TileImageInfo tinfo;
271 LayerItem *item,*item_parent;
272 TileImage *img;
273 int layerno,i;
274
275 //------ レイヤ作成
276
277 item_parent = NULL;
278
279 //グループレイヤ構造を維持するため、一覧上において上から順に作成する
280
281 for(layerno = psd->layernum - 1; layerno >= 0; layerno--)
282 {
283 if(!mPSDLoad_getLayerInfo(psd, layerno, &info))
284 return psd->err;
285
286 //フォルダ終了
287
288 if(info.group == MPSDLOAD_LAYERGROUP_END)
289 {
290 if(item_parent) item_parent = LAYERITEM(item_parent->i.parent);
291 continue;
292 }
293
294 //レイヤ作成
295
296 item = LayerList_addLayer(p->layerlist, NULL);
297 if(!item) return MPSDLOAD_ERR_ALLOC;
298
299 //位置移動 (親の最後に)
300
301 LayerList_moveitem_forLoad_topdown(p->layerlist, item, item_parent);
302
303 //名前 (UTF-8 とみなす)
304
305 LayerList_setItemName_utf8(p->layerlist, item, info.name);
306
307 //不透明度
308
309 item->opacity = (int)(info.opacity / 255.0 * 128.0 + 0.5);
310
311 //非表示
312
313 if(info.flags & MPSDLOAD_LAYERINFO_F_HIDE)
314 item->flags &= ~LAYERITEM_F_VISIBLE;
315
316 //フォルダ
317
318 if(info.group == MPSDLOAD_LAYERGROUP_EXPAND
319 || info.group == MPSDLOAD_LAYERGROUP_FOLDED)
320 {
321 item_parent = item;
322 item->flags |= LAYERITEM_F_FOLDER_EXPAND;
323 continue;
324 }
325
326 //イメージ作成
327
328 if(info.box_img.w == 0 || info.box_img.h == 0)
329 {
330 //空イメージ
331 tinfo.offx = tinfo.offy = 0;
332 tinfo.tilew = tinfo.tileh = 1;
333 }
334 else
335 {
336 tinfo.offx = info.box_img.x;
337 tinfo.offy = info.box_img.y;
338 tinfo.tilew = (info.box_img.w + 63) / 64;
339 tinfo.tileh = (info.box_img.h + 63) / 64;
340 }
341
342 img = TileImage_newFromInfo(TILEIMAGE_COLTYPE_RGBA, &tinfo);
343 if(!img) return MPSDLOAD_ERR_ALLOC;
344
345 item->img = img;
346
347 //合成モード
348
349 for(i = 0; g_blendmode[i]; i++)
350 {
351 if(g_blendmode[i] == info.blendmode)
352 {
353 item->blendmode = i;
354 break;
355 }
356 }
357 }
358
359 //------ イメージ読み込み
360
361 return _load_layer_image(p, psd, prog);
362 }
363
364 /** 一枚絵イメージから読み込み */
365
_load_from_image(DrawData * p,mPSDLoad * psd,mPopupProgress * prog)366 static int _load_from_image(DrawData *p,mPSDLoad *psd,mPopupProgress *prog)
367 {
368 LayerItem *item;
369 TileImage *img;
370 int type,i,ix,iy,w,h,chnum;
371 uint8_t *ps,*pd,f;
372 PixelRGBA pix;
373
374 w = psd->width;
375 h = psd->height;
376
377 //カラータイプ
378
379 if(psd->bits == 1)
380 type = _TYPE_MONO;
381 else if(psd->colmode == MPSD_COLMODE_GRAYSCALE)
382 type = _TYPE_GRAY;
383 else if(psd->colmode == MPSD_COLMODE_RGB && psd->img_channels >= 3)
384 type = _TYPE_RGB;
385 else
386 return MPSDLOAD_ERR_UNSUPPORTED;
387
388 //レイヤ作成
389
390 item = LayerList_addLayer(p->layerlist, NULL);
391 if(!item) return MPSDLOAD_ERR_ALLOC;
392
393 img = TileImage_new(TILEIMAGE_COLTYPE_RGBA, w, h);
394 if(!img) return MPSDLOAD_ERR_ALLOC;
395
396 item->img = img;
397
398 LayerList_setItemName_byNum(p->layerlist, item);
399
400 //------- イメージ
401
402 if(!mPSDLoad_beginImage(psd)) goto PSDERR;
403
404 //mono or gray
405
406 if(type != _TYPE_RGB)
407 {
408 mPopupProgressThreadSetMax(prog, 40);
409 mPopupProgressThreadBeginSubStep(prog, 20, h);
410
411 if(!mPSDLoad_beginImageChannel(psd)) goto PSDERR;
412 }
413
414 //
415
416 switch(type)
417 {
418 //1bit (blendimg に 8bit イメージをセット)
419 case _TYPE_MONO:
420 pd = p->blendimg->buf;
421
422 for(iy = h; iy; iy--)
423 {
424 if(!mPSDLoad_readImageChannelLine(psd)) goto PSDERR;
425
426 ps = mPSDLoad_getLineImageBuf(psd);
427
428 for(ix = w, f = 0x80; ix; ix--)
429 {
430 *(pd++) = (*ps & f)? 0: 255;
431
432 f >>= 1;
433 if(f == 0) f = 0x80, ps++;
434 }
435
436 mPopupProgressThreadIncSubStep(prog);
437 }
438 break;
439
440 //グレイスケール (blendimg に 8bit イメージをセット)
441 case _TYPE_GRAY:
442 pd = p->blendimg->buf;
443
444 for(iy = h; iy; iy--)
445 {
446 if(!mPSDLoad_readImageChannelLine(psd)) goto PSDERR;
447
448 memcpy(pd, mPSDLoad_getLineImageBuf(psd), w);
449
450 pd += w;
451
452 mPopupProgressThreadIncSubStep(prog);
453 }
454 break;
455
456 //RGB or RGBA
457 case _TYPE_RGB:
458 chnum = psd->img_channels;
459 if(chnum > 4) chnum = 4;
460
461 mPopupProgressThreadSetMax(prog, chnum * 10 + 20);
462
463 //RGB (p->blendimg->buf にセット)
464
465 for(i = 0; i < 3; i++)
466 {
467 if(!mPSDLoad_beginImageChannel(psd)) goto PSDERR;
468
469 pd = p->blendimg->buf + i;
470
471 mPopupProgressThreadBeginSubStep(prog, 10, h);
472
473 for(iy = h; iy; iy--)
474 {
475 if(!mPSDLoad_readImageChannelLine(psd)) goto PSDERR;
476
477 ps = mPSDLoad_getLineImageBuf(psd);
478
479 for(ix = w; ix; ix--, pd += 3)
480 *pd = *(ps++);
481
482 mPopupProgressThreadIncSubStep(prog);
483 }
484 }
485
486 //
487
488 if(chnum == 3)
489 //A なしなら ImageBuf24 としてセット
490 TileImage_setImage_fromImageBuf24(img, p->blendimg, prog, TRUE);
491 else
492 {
493 //blendimg->buf + A
494
495 if(!mPSDLoad_beginImageChannel(psd)) goto PSDERR;
496
497 mPopupProgressThreadBeginSubStep(prog, 10, h);
498
499 pd = p->blendimg->buf;
500
501 for(iy = 0; iy < h; iy++)
502 {
503 if(!mPSDLoad_readImageChannelLine(psd)) goto PSDERR;
504
505 ps = mPSDLoad_getLineImageBuf(psd);
506
507 for(ix = 0; ix < w; ix++, ps++, pd += 3)
508 {
509 if(*ps)
510 {
511 pix.r = pd[0];
512 pix.g = pd[1];
513 pix.b = pd[2];
514 pix.a = *ps;
515
516 TileImage_setPixel_new(img, ix, iy, &pix);
517 }
518 }
519
520 mPopupProgressThreadIncSubStep(prog);
521 }
522 }
523 break;
524 }
525
526 //mono or gray
527
528 if(type != _TYPE_RGB)
529 {
530 mPopupProgressThreadBeginSubStep(prog, 20, h);
531
532 TileImage_setImage_from8bitGray(img, p->blendimg->buf, w, h, prog);
533 }
534
535 return MPSDLOAD_ERR_OK;
536
537 PSDERR:
538 return psd->err;
539 }
540
541 /** PSD 読み込み */
542
drawFile_load_psd(DrawData * p,const char * filename,mPopupProgress * prog,char ** errmes)543 mBool drawFile_load_psd(DrawData *p,const char *filename,mPopupProgress *prog,char **errmes)
544 {
545 mPSDLoad *psd;
546 mBool ret = FALSE;
547 int err = -1,horz,vert;
548
549 /* err: -1 で psd->err、-2 でサイズ制限、それ以外は PSD エラー */
550
551 //作成
552
553 psd = mPSDLoad_new();
554 if(!psd)
555 {
556 err = MPSDLOAD_ERR_ALLOC;
557 goto ERR;
558 }
559
560 //開く
561
562 if(!mPSDLoad_openFile(psd, filename)) goto ERR;
563
564 //画像サイズ制限
565
566 if(psd->width > IMAGE_SIZE_MAX || psd->height > IMAGE_SIZE_MAX)
567 {
568 err = -2;
569 goto ERR;
570 }
571
572 //新規イメージ
573
574 if(!drawImage_new(p, psd->width, psd->height, -1, FALSE))
575 {
576 err = MPSDLOAD_ERR_ALLOC;
577 goto ERR;
578 }
579
580 //画像リソース
581
582 if(mPSDLoad_readResource_resolution_dpi(psd, &horz, &vert))
583 p->imgdpi = horz;
584
585 //レイヤ or 一枚絵イメージ
586
587 if(mPSDLoad_isHaveLayer(psd))
588 {
589 //レイヤ読み込み
590
591 if(!mPSDLoad_beginLayer(psd)) goto ERR;
592
593 err = _load_from_layer(p, psd, prog);
594
595 mPSDLoad_endLayer(psd);
596 }
597 else
598 {
599 //レイヤなしの場合は一枚絵イメージから読み込み
600
601 err = _load_from_image(p, psd, prog);
602 }
603
604 //成功
605
606 if(err == MPSDLOAD_ERR_OK)
607 {
608 p->curlayer = LayerList_getItem_top(p->layerlist);
609 ret = TRUE;
610 }
611
612 //---------
613
614 ERR:
615 if(!ret)
616 {
617 if(err == -2)
618 *errmes = mStrdup("image size is large");
619 else
620 *errmes = mStrdup(mPSDLoad_getErrorMessage((err == -1)? psd->err: err));
621 }
622
623 mPSDLoad_close(psd);
624
625 return ret;
626 }
627
628
629 //=============================
630 // 保存
631 //=============================
632
633
634 /** 一枚絵イメージ書き込み */
635
_psdimage_write(DrawData * p,mPSDSave * psd,int type,mPopupProgress * prog)636 static mBool _psdimage_write(DrawData *p,mPSDSave *psd,int type,mPopupProgress *prog)
637 {
638 uint8_t *ps,*pd,*dstbuf,val,f;
639 int w,h,i,j,ix,iy;
640
641 if(!mPSDSave_beginImage(psd)) return FALSE;
642
643 w = p->imgw;
644 h = p->imgh;
645 ps = p->blendimg->buf;
646
647 dstbuf = mPSDSave_getLineImageBuf(psd);
648
649 switch(type)
650 {
651 //RGB
652 case _TYPE_RGB:
653 mPopupProgressThreadBeginSubStep_onestep(prog, 30, h * 3);
654
655 for(i = 0; i < 3; i++)
656 {
657 mPSDSave_beginImageChannel(psd);
658
659 ps = p->blendimg->buf + i;
660
661 for(iy = h; iy > 0; iy--)
662 {
663 pd = dstbuf;
664
665 for(ix = w; ix > 0; ix--, ps += 3)
666 *(pd++) = *ps;
667
668 mPSDSave_writeImageChannelLine(psd);
669
670 mPopupProgressThreadIncSubStep(prog);
671 }
672
673 mPSDSave_endImageChannel(psd);
674 }
675 break;
676
677 //グレイスケール
678 case _TYPE_GRAY:
679 mPopupProgressThreadBeginSubStep_onestep(prog, 20, h);
680
681 mPSDSave_beginImageChannel(psd);
682
683 for(iy = h; iy > 0; iy--)
684 {
685 pd = dstbuf;
686
687 for(ix = w; ix > 0; ix--, ps += 3)
688 *(pd++) = _TOGRAY(ps[0], ps[1], ps[2]);
689
690 mPSDSave_writeImageChannelLine(psd);
691
692 mPopupProgressThreadIncSubStep(prog);
693 }
694
695 mPSDSave_endImageChannel(psd);
696 break;
697
698 //mono (白=0、それ以外は1)
699 case _TYPE_MONO:
700 mPopupProgressThreadBeginSubStep_onestep(prog, 20, h);
701
702 mPSDSave_beginImageChannel(psd);
703
704 for(iy = h; iy > 0; iy--)
705 {
706 pd = dstbuf;
707 ix = w;
708
709 for(i = (w + 7) >> 3; i > 0; i--)
710 {
711 val = 0;
712 f = 0x80;
713
714 for(j = 8; j && ix; j--, ix--, ps += 3, f >>= 1)
715 {
716 if(ps[0] != 255 || ps[1] != 255 || ps[2] != 255)
717 val |= f;
718 }
719
720 *(pd++) = val;
721 }
722
723 mPSDSave_writeImageChannelLine(psd);
724
725 mPopupProgressThreadIncSubStep(prog);
726 }
727
728 mPSDSave_endImageChannel(psd);
729 break;
730 }
731
732 return TRUE;
733 }
734
735 /** レイヤ出力 */
736
_write_layer(DrawData * p,mPSDSave * psd,int layernum,mPopupProgress * prog)737 static mBool _write_layer(DrawData *p,mPSDSave *psd,int layernum,mPopupProgress *prog)
738 {
739 LayerItem *pi_bottom,*pi;
740 mPSDSaveLayerInfo info;
741 mRect rc;
742 mBox box;
743 int ch,ix,iy;
744 uint8_t *pd;
745 PixelRGBA pix;
746
747 mPopupProgressThreadSetMax(prog, layernum * 4);
748
749 //書き込む先頭レイヤ
750
751 pi_bottom = LayerList_getItem_bottomNormal(p->layerlist);
752
753 //レイヤ開始
754
755 if(!mPSDSave_beginLayer(psd, layernum)) return FALSE;
756
757 //レイヤ情報
758
759 for(pi = pi_bottom; pi; pi = LayerItem_getPrevNormal(pi))
760 {
761 mMemzero(&info, sizeof(mPSDSaveLayerInfo));
762
763 if(TileImage_getHaveImageRect_pixel(pi->img, &rc, NULL))
764 {
765 info.left = rc.x1;
766 info.top = rc.y1;
767 info.right = rc.x2 + 1;
768 info.bottom = rc.y2 + 1;
769 }
770
771 info.name = pi->name;
772 info.opacity = (int)(pi->opacity / 128.0 * 255.0 + 0.5);
773 info.hide = !(pi->flags & LAYERITEM_F_VISIBLE);
774 info.blendmode = g_blendmode[pi->blendmode];
775 info.channels = 4;
776
777 mPSDSave_writeLayerInfo(psd, &info);
778 }
779
780 if(!mPSDSave_endLayerInfo(psd)) return FALSE;
781
782 //イメージ
783
784 for(pi = pi_bottom; pi; pi = LayerItem_getPrevNormal(pi))
785 {
786 if(!mPSDSave_beginLayerImage(psd, &box))
787 {
788 //空イメージ
789
790 mPopupProgressThreadAddPos(prog, 4);
791 }
792 else
793 {
794 //各チャンネル
795
796 for(ch = 0; ch < 4; ch++)
797 {
798 mPSDSave_beginLayerImageChannel(psd,
799 (ch == 3)? MPSD_CHANNEL_ID_ALPHA: ch);
800
801 for(iy = 0; iy < box.h; iy++)
802 {
803 pd = mPSDSave_getLineImageBuf(psd);
804
805 for(ix = 0; ix < box.w; ix++)
806 {
807 TileImage_getPixel(pi->img, box.x + ix, box.y + iy, &pix);
808
809 *(pd++) = pix.ar[ch];
810 }
811
812 mPSDSave_writeLayerImageChannelLine(psd);
813 }
814
815 mPSDSave_endLayerImageChannel(psd);
816
817 mPopupProgressThreadIncPos(prog);
818 }
819 }
820
821 mPSDSave_endLayerImage(psd);
822 }
823
824 mPSDSave_endLayer(psd);
825
826 return TRUE;
827 }
828
829 /** PSD 保存 (レイヤ維持)
830 *
831 * フォルダは保存されない。 */
832
drawFile_save_psd_layer(DrawData * p,const char * filename,mPopupProgress * prog)833 mBool drawFile_save_psd_layer(DrawData *p,const char *filename,mPopupProgress *prog)
834 {
835 mPSDSave *psd;
836 mPSDSaveInfo info;
837 mBool ret = FALSE;
838 int layernum;
839
840 //通常レイヤ数 (フォルダしかない場合はエラー)
841
842 layernum = LayerList_getNormalLayerNum(p->layerlist);
843
844 if(layernum == 0) return FALSE;
845
846 //情報
847
848 info.width = p->imgw;
849 info.height = p->imgh;
850 info.img_channels = 3;
851 info.bits = 8;
852 info.colmode = MPSD_COLMODE_RGB;
853
854 //開く
855
856 psd = mPSDSave_openFile(filename, &info,
857 ((APP_CONF->save.flags & CONFIG_SAVEOPTION_F_PSD_UNCOMPRESSED) == 0));
858
859 if(!psd) return FALSE;
860
861 //画像リソース
862
863 mPSDSave_beginResource(psd);
864
865 mPSDSave_writeResource_resolution_dpi(psd, p->imgdpi, p->imgdpi);
866 mPSDSave_writeResource_currentLayer(psd, 0);
867
868 mPSDSave_endResource(psd);
869
870 //レイヤ
871
872 if(_write_layer(p, psd, layernum, prog))
873 {
874 //一枚絵イメージ
875
876 ret = _psdimage_write(p, psd, _TYPE_RGB, prog);
877 }
878
879 mPSDSave_close(psd);
880
881 if(!ret) mDeleteFile(filename);
882
883 return ret;
884 }
885
886 /** PSD 保存 (レイヤなし)
887 *
888 * @param type 1:8bitRGB 2:grayscale 3:mono */
889
drawFile_save_psd_image(DrawData * p,int type,const char * filename,mPopupProgress * prog)890 mBool drawFile_save_psd_image(DrawData *p,int type,const char *filename,mPopupProgress *prog)
891 {
892 mPSDSave *psd;
893 mPSDSaveInfo info;
894 mBool ret;
895
896 //情報
897
898 info.width = p->imgw;
899 info.height = p->imgh;
900 info.img_channels = (type == _TYPE_RGB)? 3: 1;
901 info.bits = (type == _TYPE_MONO)? 1: 8;
902
903 switch(type)
904 {
905 case _TYPE_RGB: info.colmode = MPSD_COLMODE_RGB; break;
906 case _TYPE_GRAY: info.colmode = MPSD_COLMODE_GRAYSCALE; break;
907 default: info.colmode = MPSD_COLMODE_MONO; break;
908 }
909
910 //開く
911
912 psd = mPSDSave_openFile(filename, &info,
913 ((APP_CONF->save.flags & CONFIG_SAVEOPTION_F_PSD_UNCOMPRESSED) == 0));
914
915 if(!psd) return FALSE;
916
917 //画像リソース
918
919 mPSDSave_beginResource(psd);
920
921 mPSDSave_writeResource_resolution_dpi(psd, p->imgdpi, p->imgdpi);
922
923 mPSDSave_endResource(psd);
924
925 //レイヤなし
926
927 mPSDSave_writeLayerNone(psd);
928
929 //一枚絵イメージ
930
931 ret = _psdimage_write(p, psd, type, prog);
932
933 mPSDSave_close(psd);
934
935 if(!ret) mDeleteFile(filename);
936
937 return ret;
938 }
939