水曜日, 11月 26, 2025

Excelでの連番設定はROW関数

Excelでの連番設定はROW関数にしておくと何かと便利です。

サンプルは以下の様に設定しています。
連番A 数値のフィル
連番B B2: =ROW()をフィル
連番C C2: =ROW()-1をフィル
連番D D2: =ROW()+2をフィル
連番E E2: =ROW()*2をフィル
連番F F2: =ROW()/2をフィル
連番G G2: =SQRT(ROW())をフィル

ここで7番目の行を作字すると・・・

数値入力の行(連番A)のみ連番後抜けた状態になりますが、ROW関数を使っている行は、連番を保っています。変更の可能性は常に考慮してROW関数を利用すると良いでしょう。

サイトの改装が完了しました



22日にkaizu.comサイトの改装告知をしていましたが、その後ページが不安定でしたが不安定問題は解決し、サイトも今朝改装しました。今回はシンプルに整理しました。

TCDW8597 
もう11月も後半なので直ぐに12月ですね

Baby Alien 167
ウサギかネズミか分からない系(^o^)
雨が降っていると出かけるのも「おっくう」になるので、引きこもりへ「まっしぐら」。しかし、もう11月も後半なので直ぐに12月ですね。

火曜日, 11月 25, 2025

Photoshopで透明部分を含むデータ書き出し

質問がありましたので・・・
今更ながらですが、印刷用としてPhotoshopで透明部分を含むデータ書き出す場合について整理してみました。

レイヤーマスクにグラデーションなどで透明部分を作成したデータを・・・

8bit/チャンネル、CMYKカラーに変更して書き出します。

PSD形式以外ではTIFF形式で書き出しますが・・・

透明部分を含んでいる場合は上の設定がウッパン的です。ただし、ほとんどのアプリケーショ ンで TIFF の透明機能をサポートしていないません。また、印刷業界で一般的に使用されるソフトウエアや RIP(ラスターイメージ プロセッサ)システムが、TIFF 形式の透明度情報を適切に処理できないことがあるためです。そのため、透明部分を含んでいる場合のデータ書き出しは原則 PSD と理解した方が安全です。

勿論生成した画像はIllustratorやInDesignに配置します。

Illustratorに配置した状態。

配置画像に下に任意の色で塗り潰した矩形を配置。

レイヤーの関係はこんな感じ。

配置画像に上に任意のキャラクターなどを配置。

レイヤーの関係はこんな感じ。もし透明部分を含んだでーたとしてRGBのPNGファイルが渡された場合は、CMYKへ返還後にPSD形式で書き出せばOKです。迷ったらPSD形式ですね。

TCDW8596 
同一の別ファイルは何も問題ないのに

20年以上前のAdobe GoLive 5で作成したHTMLファイルの文字化け修正が出来ずに撃沈。同一の別ファイルは何も問題ないのに悔しい。

月曜日, 11月 24, 2025

Let's start JavaScript 88 
指定画像をキュビスム風の画像に変換

指定画像をキュビスム風の画像に変換します。あくまでも「〜風」です(^o^)

<!-- index.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>キュビスム風画像変換</title>
<style>
body {
background: #1e1e1e;
color: #eee;
font-family: sans-serif;
text-align: center;
}
canvas {
border: 1px solid #555;
margin-top: 10px;
background: #ccc;
}
.controls {
margin: 10px;
}
input[type="range"] {
width: 300px;
}
</style>
</head>
<body>
<h2>キュビスム風変換(サイズ調整対応)</h2>

<input type="file" id="fileInput" accept="image/*"><br>

<div class="controls">
<label>ブロックサイズ:
<input type="range" id="sizeSlider"
        min="5" max="80" value="25">
<span id="sizeValue">25</span>px
</label>
</div>

<canvas id="canvas"></canvas>

<script>
const fileInput = document.getElementById("fileInput");
const sizeSlider = document.getElementById("sizeSlider");
const sizeValue = document.getElementById("sizeValue");
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

let img = null;
let imgData = null;

// ファイル選択 → キュビスム変換
fileInput.addEventListener("change", e => {
const file = e.target.files[0];
if (!file) return;
img = new Image();
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
imgData = ctx.getImageData(0, 0, img.width, img.height);
drawCubism();
};
img.src = URL.createObjectURL(file);
});

// サイズ変更スライダー
sizeSlider.addEventListener("input", () => {
sizeValue.textContent = sizeSlider.value;
if (imgData) drawCubism();
});

function drawCubism() {
const blockSize = parseInt(sizeSlider.value);
const width = canvas.width;
const height = canvas.height;
const data = imgData.data;

// 背景をリセット
ctx.fillStyle = "#e0e0e0";
ctx.fillRect(0, 0, width, height);

// 幾何的に分解再構成
const total = (width * height) / (blockSize * blockSize);
for (let i = 0; i < total; i++) {
const x = Math.random() * width;
const y = Math.random() * height;
const px = (Math.floor(y) * width + Math.floor(x)) * 4;
const r = data[px];
const g = data[px + 1];
const b = data[px + 2];

const sides = 3 + Math.floor(Math.random() * 3); // 3〜5角形
const angle = Math.random() * Math.PI * 2;
const size = blockSize * (0.8 + Math.random() * 0.4);

ctx.beginPath();
for (let j = 0; j < sides; j++) {
const theta = angle + j * (Math.PI * 2 / sides);
const dx = x + Math.cos(theta) * size;
const dy = y + Math.sin(theta) * size;
j === 0 ? ctx.moveTo(dx, dy) : ctx.lineTo(dx, dy);
}
ctx.closePath();

// 塗りと線でキュビスム感
ctx.fillStyle =
        `rgba(${r},${g},${b},${0.7 + Math.random()*0.3})`;
ctx.fill();
if (Math.random() < 0.1) {
ctx.strokeStyle = `rgba(0,0,0,${0.2 + Math.random()*0.3})`;
ctx.lineWidth = 0.5 + Math.random() * 1.2;
ctx.stroke();
}
}
}
</script>
</body>
</html>
<!-- index.html -->

実行したら画像を指定するだけです。

元画像

結果はこんな感じです。ブロックサイズを調整すれば・・・

ソレっぽい雰囲気を演出できます。

TCDW8595 
勘違いと思い込みが重なると怖いですね〜

HTMLにドップリの状態が少し続いていたら、印刷用のデータに貼り付ける画像をウッカリPNGで貼ってしまい苦笑い。直ぐに気がつきましたが、勘違いと思い込みが重なると怖いですね〜。

日曜日, 11月 23, 2025

ペットボトルキャップを綺麗にスライス







ペットボトルキャップを綺麗にスライスする治具を作成しました。過去にも作成していますが、今回の方が簡単かつ汎用性が高いです。


用意するのは適当な板です。薄めで厚みの微調整はプラ板などを使うと便利です。

アサリの無いのこぎりに両面テープで板を張り付けます。

後はペットボトルを抑えてカットするだけです。

抑え方を逆にすると厚みも変わります。よく使う厚みに合わせて板あるいはプラ板を用意しておきます。

TCDW8594 
やたらと疲れる日があるのが謎です

同じルーチンで動いているのに、やたらと疲れる日があるのが謎です。まっ精神的な要因が加算されるのでしょう、しかも無意識なのに実はジワジワと浸食されるみたいな〜かな。

土曜日, 11月 22, 2025

modoローポリモデリング 66 
頂点、エッジ、ポリゴン別、目のモデリング

顔のパーツは位置によって激変しますが、ローポリゴンでの処理は基準を頂点、エッジ、ポリゴンのどこに設定するかで調整出来ます。

ベースとしたオブジェクトです。

頂点の場合・・・

そのままベベル処理し・・・

ポリゴン選択で生成された菱形を選択してベベルを二重に設定して押し込みます。必要に応じてエッジなどを調整し・・・

球体を入れれば完成です。

エッジの場合は・・・

一度ベベル処理をしてから・・・

拡大縮小で形状を調整します。

ポリゴン選択に切り換えて、ベベルを二重に設定して押し込みます。必要に応じてエッジなどを調整し・・・

球体を入れれば完成です。

ポリゴンの場合は・・・

目の間が空きすぎてしまうので、ベベル処理前に位置調整します。

そのままベベルを二重に設定して押し込みます。必要に応じてエッジなどを調整し・・・

生成された穴のエッジを選択して上面、左右などに表示を切り替えて回転調整する必要があります。

細部調整がカナリ必要です。最後に球体を入れれば完成です。

modo 17.1v1 

TCDW8593 
私が理解できるのは5人ぐらいかな?

Baby Alien 166
ウルトラ系(^o^)
そう言えば、今も続いているウルトラマンシリーズで57人(人と数えて良いのか謎)のウルトラヒーローが出たらしいのですが、私が理解できるのは初期の5人ぐらいかな?

金曜日, 11月 21, 2025

JavaScriptでAI遊び 80 
Illustratorでグラデーションを中間色ベタ塗りに


Illustratorでグラデーションを中間色ベタ塗りに変更します。これによりブラシなどに活用できます。

/*
* グラデーション塗り → 50%位置の中間色(実測)に変更
* - 選択中の各オブジェクトの塗りが Gradient のものだけ処理
* - 50%位置に隣接する2つのストップを見つけ、線形補間
* - 最終色はドキュメントのカラー空間(RGB / CMYK)で設定
* - Gray / Spot / Lab なども内部で変換して処理
* 注意: Illustrator の「midPoint」は考慮せず(rampPoint のみ尊重)。
* midPoint(ミッドポイント)隣接する2つのストップの間で、
* 色の比率が50:50になる位置を決めるパラメータ。
* デフォルトは 50(真ん中)で、移動でブレンドの寄り方が変化。 * rampPoint(ランプポイント)ストップの位置を表す数値。 * 0〜100 (%) で、グラデーション全体に対してその色が置かれる位置。
*/

(function () {
if (app.documents.length === 0)
    { alert("ドキュメントを開いてください。"); return; }
var doc = app.activeDocument;
if (!doc.selection || doc.selection.length === 0)
    { alert("オブジェクトを選択してください。"); return; }

var targetIsRGB = (doc.documentColorSpace ===
    DocumentColorSpace.RGB);
var changed = 0, skipped = 0;

// ImageColorSpace 列挙の短縮
var ICS = ImageColorSpace;

function colorToArray(c) {
// 任意の Color を「その色が属する空間の配列値 + 空間種別」を返す
// 戻り値: {space: ICS.RGB|CMYK|GRAY|LAB, values:[...]}
if (c.typename === "RGBColor") return { space: ICS.RGB,
        values: [c.red, c.green, c.blue] };
if (c.typename === "CMYKColor") return { space: ICS.CMYK,
        values: [c.cyan, c.magenta, c.yellow, c.black] };
if (c.typename === "GrayColor")
        return { space: ICS.Gray, values: [c.gray] };
if (c.typename === "LabColor")
        return { space: ICS.LAB, values: [c.l, c.a, c.b] };
if (c.typename === "SpotColor")
         return colorToArray(c.spot.color);
    // 中身の実色で再帰
// その他(パターン/グラデ/なし)はここには来ない想定
throw new Error("未対応のカラータイプ: " + c.typename);
}

function convert(values, srcSpace, dstSpace) {
// app.convertSampleColor(src, srcArray, dst, purpose)
// purpose: ImageColorConvertPurpose.defaultpurpose
return app.convertSampleColor(srcSpace, values, dstSpace,
ImageColorConvertPurpose.defaultpurpose);
}

function makeSolidColorFromArray(arr, useRGB) {
if (useRGB) {
var rgb = new RGBColor();
rgb.red = arr[0]; rgb.green = arr[1]; rgb.blue = arr[2];
return rgb;
} else {
var cmyk = new CMYKColor();
cmyk.cyan = arr[0]; cmyk.magenta = arr[1];
        cmyk.yellow = arr[2]; cmyk.black = arr[3];
return cmyk;
}
}

function getColorAt50Percent(gradient) {
// 0..100 の rampPoint を持つ gradientStops から、
    // pos=50 に隣接する2ストップを見つけ補間
var stops = gradient.gradientStops;
if (stops.length === 0) return null;
if (stops.length === 1) return stops[0].color;

// ストップを rampPoint 昇順で収集
var list = [];
for (var i = 0; i < stops.length; i++) {
list.push({ p: stops[i].rampPoint, c: stops[i].color });
}
list.sort(function (a, b) { return a.p - b.p; });

var pos = 50;
// ちょうど一致
for (var j = 0; j < list.length; j++) {
if (Math.abs(list[j].p - pos) < 0.0001) return list[j].c;
}
// 区間を特定
var a = list[0], b = list[list.length - 1];
for (var k = 0; k < list.length - 1; k++) {
if (list[k].p <= pos && pos <= list[k + 1].p)
        { a = list[k]; b = list[k + 1]; break; }
}
var t = (pos - a.p) / Math.max(1e-6, (b.p - a.p)); // 0..1

// 両端色をドキュメント空間へ変換
var dst = targetIsRGB ? ICS.RGB : ICS.CMYK;

var A = colorToArray(a.c);
var B = colorToArray(b.c);

var aDst = (A.space === dst) ? A.values.slice(0) :
        convert(A.values, A.space, dst);
var bDst = (B.space === dst) ? B.values.slice(0) :
        convert(B.values, B.space, dst);

// 線形補間
var out = [];
var n = aDst.length;
for (var m = 0; m < n; m++) {
out[m] = aDst[m] + (bDst[m] - aDst[m]) * t;
}
return makeSolidColorFromArray(out, targetIsRGB);
}

function processItem(it) {
try {
// PathItem / CompoundPathItem の塗りを処理
if (it.typename === "PathItem") {
if (it.filled && it.fillColor && it.fillColor.typename ===
        "GradientColor")
        {var col = getColorAt50Percent(it.fillColor.gradient);
if (col) { it.fillColor = col; changed++; return; }
}
} else if (it.typename === "CompoundPathItem") {
// コンパウンドは子パスの塗りに依存
for (var i = 0; i < it.pathItems.length; i++) {
var p = it.pathItems[i];
if (p.filled && p.fillColor && p.fillColor.typename ===
            "GradientColor") {
var col2 = getColorAt50Percent(p.fillColor.gradient);
if (col2) { p.fillColor = col2; changed++; }
}
}
return;
} else if ("pageItems" in it) {
// グループ/テキストアウトラインなど再帰
for (var j = 0; j < it.pageItems.length; j++)
        processItem(it.pageItems[j]);
return;
}
skipped++;
} catch (e) {
// 個々のアイテムで失敗しても継続
$.writeln(e);
skipped++;
}
}

// 選択全体を処理
var sel = doc.selection;
for (var s = 0; s < sel.length; s++) processItem(sel[s]);

alert("完了: 中間色に変更 " + changed + " 件" +
    (skipped ? "(対象外 " + skipped + " 件)" : ""));
})();

今回は3匹の熊さんを選択して実行すると・・・

完了が表示され・・・

ベタ塗りに変換されます。グラデーションは2色間だけでなく複雑なモノでもOKです。