psdparse 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {psdparse-0.2.0 → psdparse-0.2.2}/PKG-INFO +1 -1
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psddata.h +16 -2
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdengine.cpp +61 -6
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdparse.cpp +29 -1
- {psdparse-0.2.0 → psdparse-0.2.2}/pyproject.toml +1 -1
- {psdparse-0.2.0 → psdparse-0.2.2}/python/psdparse_module.cpp +12 -2
- {psdparse-0.2.0 → psdparse-0.2.2}/.gitignore +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/CMakeLists.txt +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/CMakePresets.json +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/LICENSE +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/Makefile +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/README.md +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/docs/ARCHITECTURE.md +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/docs/PYTHON_API.md +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/docs/ROADMAP.md +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/CMakeLists.txt +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/bmp.cpp +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psd_cli.cpp +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdbase.h +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psddesc.cpp +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psddesc.h +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdengine.h +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdfile.cpp +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdfile.h +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdimage.cpp +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdlayer.cpp +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdlayer.h +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdparse.h +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdresource.cpp +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdresource.h +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdwrite.cpp +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/psdparse/psdwrite.h +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/python/CMakeLists.txt +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/tests/conftest.py +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/tests/test_header.py +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/tests/test_images.py +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/tests/test_layers.py +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/tests/test_save.py +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/tests/test_text.py +0 -0
- {psdparse-0.2.0 → psdparse-0.2.2}/tools/psd_export.py +0 -0
|
@@ -157,6 +157,8 @@ namespace psd {
|
|
|
157
157
|
int width;
|
|
158
158
|
int depth;
|
|
159
159
|
int mode;
|
|
160
|
+
double hres = 72.0; // 水平解像度 dpi (image resource 1005)。 既定 72。
|
|
161
|
+
double vres = 72.0; // 垂直解像度 dpi。
|
|
160
162
|
};
|
|
161
163
|
|
|
162
164
|
// RGBAカラー
|
|
@@ -403,10 +405,21 @@ namespace psd {
|
|
|
403
405
|
int tracking; // トラッキング (字送り, 1/1000 em)
|
|
404
406
|
int kerning; // 手動カーニング
|
|
405
407
|
bool autoKerning; // 自動カーニング (メトリクス/オプティカル) 有効
|
|
408
|
+
bool sizeInherited; // FontSize を既定 StyleSheet から継承したか。
|
|
409
|
+
// 継承分は nominal pt なので dpi/72 で px 化する
|
|
410
|
+
// (明示 run の FontSize は既に解決済み px)。内部用。
|
|
406
411
|
|
|
407
412
|
TextStyleRun()
|
|
408
413
|
: length(0), fontSize(0.0f), color{0,0,0,1}, hasColor(false),
|
|
409
|
-
tracking(0), kerning(0), autoKerning(false) {}
|
|
414
|
+
tracking(0), kerning(0), autoKerning(false), sizeInherited(false) {}
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
// 段落単位の情報 (EngineDict/ParagraphRun)。 段落は本文中の改行 (\r) 区切り。
|
|
418
|
+
struct TextParagraph {
|
|
419
|
+
int length; // 段落の文字数 (UTF-16 コードユニット, RunLengthArray)
|
|
420
|
+
int justification; // 行揃え 0=左 1=右 2=中央 (3..=両端揃え系)
|
|
421
|
+
|
|
422
|
+
TextParagraph() : length(0), justification(0) {}
|
|
410
423
|
};
|
|
411
424
|
|
|
412
425
|
// テキストレイヤ情報 (追加レイヤ情報 'TySh' 由来)。
|
|
@@ -415,8 +428,9 @@ namespace psd {
|
|
|
415
428
|
u16str text; // 本文全体 (改行は \r)
|
|
416
429
|
double transform[6]; // アフィン変換 xx,xy,yx,yy,tx,ty
|
|
417
430
|
std::string orientation; // "horizontal" / "vertical"
|
|
418
|
-
int justification; // 段落の行揃え 0=左 1=右 2=中央 (
|
|
431
|
+
int justification; // 段落の行揃え 0=左 1=右 2=中央 (先頭段落; 後方互換)
|
|
419
432
|
std::vector<TextStyleRun> runs;
|
|
433
|
+
std::vector<TextParagraph> paragraphs; // 段落別 (行揃えが段落で変わる box text 用)
|
|
420
434
|
|
|
421
435
|
TextLayerData()
|
|
422
436
|
: present(false), transform{1,0,0,1,0,0},
|
|
@@ -204,6 +204,37 @@ namespace {
|
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
// 既定 StyleSheet (ResourceDict/StyleSheetSet[0]/StyleSheetData)。
|
|
208
|
+
// box text の基準 run は FontSize/Font 等の StyleSheetData を持たず、 この既定を
|
|
209
|
+
// 継承する。 これを読まないと FontSize=0 になる (実表示は既定サイズ)。
|
|
210
|
+
float defSize = 0.0f; int defFontIdx = -1; int defTracking = 0;
|
|
211
|
+
float defColor[4] = {0, 0, 0, 1}; bool defHasColor = false;
|
|
212
|
+
{
|
|
213
|
+
Node *rd2 = dget(root, "ResourceDict");
|
|
214
|
+
Node *sss = dget(rd2, "StyleSheetSet");
|
|
215
|
+
Node *dssd = 0;
|
|
216
|
+
if (sss && sss->kind == Node::ARRAY && !sss->arr.empty()) {
|
|
217
|
+
dssd = dget(sss->arr[0], "StyleSheetData");
|
|
218
|
+
if (!dssd) dssd = dget(dget(sss->arr[0], "StyleSheet"), "StyleSheetData");
|
|
219
|
+
}
|
|
220
|
+
if (dssd) {
|
|
221
|
+
Node *f = dget(dssd, "Font");
|
|
222
|
+
if (f && f->kind == Node::NUMBER) defFontIdx = (int)f->num;
|
|
223
|
+
Node *fs = dget(dssd, "FontSize");
|
|
224
|
+
if (fs && fs->kind == Node::NUMBER) defSize = (float)fs->num;
|
|
225
|
+
Node *tk = dget(dssd, "Tracking");
|
|
226
|
+
if (tk && tk->kind == Node::NUMBER) defTracking = (int)tk->num;
|
|
227
|
+
Node *vals = dget(dget(dssd, "FillColor"), "Values");
|
|
228
|
+
if (vals && vals->kind == Node::ARRAY && vals->arr.size() >= 4) {
|
|
229
|
+
defColor[3] = (float)vals->arr[0]->num; // A
|
|
230
|
+
defColor[0] = (float)vals->arr[1]->num; // R
|
|
231
|
+
defColor[1] = (float)vals->arr[2]->num; // G
|
|
232
|
+
defColor[2] = (float)vals->arr[3]->num; // B
|
|
233
|
+
defHasColor = true;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
207
238
|
// ラン単位スタイル (EngineDict/StyleRun)
|
|
208
239
|
if (engine) {
|
|
209
240
|
Node *styleRun = dget(engine, "StyleRun");
|
|
@@ -213,6 +244,16 @@ namespace {
|
|
|
213
244
|
for (size_t i = 0; i < runArray->arr.size(); i++) {
|
|
214
245
|
Node *ssd = dget(dget(runArray->arr[i], "StyleSheet"), "StyleSheetData");
|
|
215
246
|
TextStyleRun r;
|
|
247
|
+
// 既定を先に適用 (未指定フィールドの継承)。
|
|
248
|
+
r.fontSize = defSize;
|
|
249
|
+
r.sizeInherited = true; // 既定継承 (下で run が上書きすれば false)
|
|
250
|
+
r.tracking = defTracking;
|
|
251
|
+
if (defFontIdx >= 0 && defFontIdx < (int)fonts.size()) r.font = fonts[defFontIdx];
|
|
252
|
+
if (defHasColor) {
|
|
253
|
+
r.color[0] = defColor[0]; r.color[1] = defColor[1];
|
|
254
|
+
r.color[2] = defColor[2]; r.color[3] = defColor[3];
|
|
255
|
+
r.hasColor = true;
|
|
256
|
+
}
|
|
216
257
|
if (runLen && runLen->kind == Node::ARRAY && i < runLen->arr.size() &&
|
|
217
258
|
runLen->arr[i]->kind == Node::NUMBER) {
|
|
218
259
|
r.length = (int)runLen->arr[i]->num;
|
|
@@ -224,7 +265,10 @@ namespace {
|
|
|
224
265
|
if (idx >= 0 && idx < (int)fonts.size()) r.font = fonts[idx];
|
|
225
266
|
}
|
|
226
267
|
Node *fsz = dget(ssd, "FontSize");
|
|
227
|
-
if (fsz && fsz->kind == Node::NUMBER)
|
|
268
|
+
if (fsz && fsz->kind == Node::NUMBER) {
|
|
269
|
+
r.fontSize = (float)fsz->num; // 明示 = 解決済み px
|
|
270
|
+
r.sizeInherited = false;
|
|
271
|
+
}
|
|
228
272
|
Node *trk = dget(ssd, "Tracking");
|
|
229
273
|
if (trk && trk->kind == Node::NUMBER) r.tracking = (int)trk->num;
|
|
230
274
|
Node *krn = dget(ssd, "Kerning");
|
|
@@ -245,12 +289,23 @@ namespace {
|
|
|
245
289
|
}
|
|
246
290
|
}
|
|
247
291
|
|
|
248
|
-
//
|
|
249
|
-
|
|
292
|
+
// 段落別の行揃え (ParagraphRun)。 out.justification は先頭段落 (後方互換)、
|
|
293
|
+
// out.paragraphs に全段落分 (length + justification) を格納する。
|
|
294
|
+
Node *paraRun = dget(engine, "ParagraphRun");
|
|
295
|
+
Node *paraArr = dget(paraRun, "RunArray");
|
|
296
|
+
Node *paraLen = dget(paraRun, "RunLengthArray");
|
|
250
297
|
if (paraArr && paraArr->kind == Node::ARRAY && !paraArr->arr.empty()) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
298
|
+
for (size_t i = 0; i < paraArr->arr.size(); i++) {
|
|
299
|
+
TextParagraph p;
|
|
300
|
+
if (paraLen && paraLen->kind == Node::ARRAY && i < paraLen->arr.size() &&
|
|
301
|
+
paraLen->arr[i]->kind == Node::NUMBER)
|
|
302
|
+
p.length = (int)paraLen->arr[i]->num;
|
|
303
|
+
Node *props = dget(dget(paraArr->arr[i], "ParagraphSheet"), "Properties");
|
|
304
|
+
Node *just = dget(props, "Justification");
|
|
305
|
+
if (just && just->kind == Node::NUMBER) p.justification = (int)just->num;
|
|
306
|
+
out.paragraphs.push_back(p);
|
|
307
|
+
}
|
|
308
|
+
out.justification = out.paragraphs[0].justification; // 後方互換
|
|
254
309
|
}
|
|
255
310
|
}
|
|
256
311
|
|
|
@@ -35,11 +35,22 @@ Data::processParsed()
|
|
|
35
35
|
success = loadResourceLayerComps(*this, res);
|
|
36
36
|
break;
|
|
37
37
|
|
|
38
|
+
case 1005: { // 0x03ED -- ResolutionInfo。 hRes/vRes は Fixed 16.16 の dpi。
|
|
39
|
+
if (res.data) {
|
|
40
|
+
int32_t h = res.data->getInt32(); // hRes (Fixed 16.16)
|
|
41
|
+
(void)res.data->getInt16(); // hResUnit
|
|
42
|
+
(void)res.data->getInt16(); // widthUnit
|
|
43
|
+
int32_t v = res.data->getInt32(); // vRes (Fixed 16.16)
|
|
44
|
+
if (h > 0) header.hres = (double)(uint32_t)h / 65536.0;
|
|
45
|
+
if (v > 0) header.vres = (double)(uint32_t)v / 65536.0;
|
|
46
|
+
}
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
default: // 未実装はそのままスルー
|
|
39
51
|
case 1000: // 0x03E8 -- (Obsolete--Photoshop 2.0 only ) Contains five 2-byte values: number of channels, rows, columns, depth, and mode
|
|
40
52
|
case 1001: // 0x03E9 -- Macintosh print manager print info record
|
|
41
53
|
case 1003: // 0x03EB -- (Obsolete--Photoshop 2.0 only ) Indexed color table
|
|
42
|
-
case 1005: // 0x03ED -- ResolutionInfo structure. See Appendix A in Photoshop API Guide.pdf.
|
|
43
54
|
case 1006: // 0x03EE -- Names of the alpha channels as a series of Pascal strings.
|
|
44
55
|
case 1007: // 0x03EF -- (Obsolete) See ID 1077DisplayInfo structure. See Appendix A in Photoshop API Guide.pdf.
|
|
45
56
|
case 1008: // 0x03F0 -- The caption as a Pascal string.
|
|
@@ -295,6 +306,23 @@ Data::processParsed()
|
|
|
295
306
|
}
|
|
296
307
|
}
|
|
297
308
|
|
|
309
|
+
// テキスト run の FontSize を px に正規化する (レイヤ解析後・解像度確定後)。 明示
|
|
310
|
+
// run の FontSize は既に解決済み px だが、 既定 StyleSheet から継承した分は nominal
|
|
311
|
+
// pt なので dpi/72 を掛ける (300dpi なら 12pt → 50px)。
|
|
312
|
+
{
|
|
313
|
+
double sc = header.hres / 72.0;
|
|
314
|
+
if (sc != 1.0) {
|
|
315
|
+
for (uint32_t li = 0; li < layerList.size(); li++) {
|
|
316
|
+
TextLayerData &td = layerList[li].textData;
|
|
317
|
+
if (!td.present) continue;
|
|
318
|
+
for (size_t ri = 0; ri < td.runs.size(); ri++) {
|
|
319
|
+
if (td.runs[ri].sizeInherited)
|
|
320
|
+
td.runs[ri].fontSize *= (float)sc;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
298
326
|
return success;
|
|
299
327
|
}
|
|
300
328
|
|
|
@@ -52,7 +52,7 @@ py::object layerText(const psd::LayerInfo &l) {
|
|
|
52
52
|
py::dict rd;
|
|
53
53
|
rd["length"] = r.length; // UTF-16 code units covered by this run
|
|
54
54
|
rd["font"] = py::cast(r.font); // resolved font-set name
|
|
55
|
-
rd["size_px"] = r.fontSize; //
|
|
55
|
+
rd["size_px"] = r.fontSize; // px (文書解像度で換算済み; 継承分は pt×dpi/72)
|
|
56
56
|
rd["tracking"] = r.tracking; // 1/1000 em
|
|
57
57
|
rd["kerning"] = r.kerning; // manual kerning
|
|
58
58
|
rd["auto_kerning"] = r.autoKerning; // metrics/optical kerning on
|
|
@@ -63,6 +63,14 @@ py::object layerText(const psd::LayerInfo &l) {
|
|
|
63
63
|
runs.append(rd);
|
|
64
64
|
}
|
|
65
65
|
d["runs"] = runs;
|
|
66
|
+
py::list paras;
|
|
67
|
+
for (const auto &p : t.paragraphs) {
|
|
68
|
+
py::dict pd;
|
|
69
|
+
pd["length"] = p.length; // UTF-16 code units
|
|
70
|
+
pd["justification"] = p.justification; // 0=left 1=right 2=center
|
|
71
|
+
paras.append(pd);
|
|
72
|
+
}
|
|
73
|
+
d["paragraphs"] = paras; // 段落別行揃え (段落=改行区切り)
|
|
66
74
|
return std::move(d);
|
|
67
75
|
}
|
|
68
76
|
|
|
@@ -134,7 +142,9 @@ PYBIND11_MODULE(psdparse, m) {
|
|
|
134
142
|
.def_readonly("height", &psd::Header::height)
|
|
135
143
|
.def_readonly("width", &psd::Header::width)
|
|
136
144
|
.def_readonly("depth", &psd::Header::depth)
|
|
137
|
-
.def_readonly("mode", &psd::Header::mode)
|
|
145
|
+
.def_readonly("mode", &psd::Header::mode)
|
|
146
|
+
.def_readonly("hres", &psd::Header::hres) // 水平解像度 dpi (既定 72)
|
|
147
|
+
.def_readonly("vres", &psd::Header::vres); // 垂直解像度 dpi
|
|
138
148
|
|
|
139
149
|
py::class_<psd::ChannelInfo>(m, "ChannelInfo")
|
|
140
150
|
.def_readonly("id", &psd::ChannelInfo::id)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|