cafe_basics_duo 0.1.51 → 0.1.52

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cafe_basics_duo.rb +186 -111
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bce6014d5547f54cf0a19c0bec6f07359d2bdd76ed89ec46d6b99a65ad2d1b3
4
- data.tar.gz: 4337221b8ca009ec93d5ad70555cc22fb699fac7feed3ec2b15ee7d8b6381d87
3
+ metadata.gz: 60647955187b2b942307988080314021176bf5359a4899611fd88293402edc38
4
+ data.tar.gz: 3d16d1ee3a8c39c168b031f4fcea42cf995981843523851f832b82f616d8e1ff
5
5
  SHA512:
6
- metadata.gz: 2179f2e8fa67a6f30edd7e7291c7d2e1e6ea6f9ca7aa0df83db1e021c75d396488b589a739bb16e4bbf8a19d274ef92d8503f36f41d7af3a039bb47cf892c72a
7
- data.tar.gz: 335456160dcb7f18b5afebe98b002ad47b159c2880d9f21784591b49052f0032cffa42d725614c5ca1d8c2df7eb1b8ae9925b5b2619079a6ae3db5f630ac3900
6
+ metadata.gz: fb237f7fb35781a4e4f04d83b224ff6b22fece83cee9dec8c39fa3e01178b6a8db18e3e9dc9e4e14fd33d444740b1173fbdff9031228948b093de450cf1032d3
7
+ data.tar.gz: c06a8c8484d36289cab1c0efa7a5d1b1c557331c86a78e4539a92a1d89193c8034bfc6560753936109f364c6d5e82e654caf52cb7b523c2dd531f34c32fbcfcb
@@ -2096,83 +2096,111 @@ class Wordpress
2096
2096
 
2097
2097
 
2098
2098
 
2099
- def auto_image(keyword = nil)
2100
- keyword ||= @keyword
2101
- puts "키워드: #{keyword}"
2102
-
2103
- client = HTTPClient.new
2104
- client.default_header = {
2105
- 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
2106
- '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
2107
- 'Accept' => 'application/json, text/javascript, */*; q=0.01',
2108
- 'Accept-Language' => 'en-US,en;q=0.9',
2109
- 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
2110
- 'X-Requested-With' => 'XMLHttpRequest'
2111
- }
2099
+ def crop_image_height_under_width(path, min_crop_ratio = 0.625)
2100
+ img = Magick::Image.read(path).first
2101
+ width = img.columns
2102
+ height = img.rows
2112
2103
 
2113
- retry_count = 0
2114
- max_retries = 10
2115
- results = []
2116
2104
 
2117
- begin
2118
- page = rand(1..15)
2119
- url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
2120
- puts "Request URL: #{url}"
2121
- res = client.get(url)
2122
-
2123
- unless res.status == 200
2124
- puts "HTTP Error: #{res.status}"
2125
- raise "HTTP Error"
2126
- end
2127
2105
 
2128
- json = JSON.parse(res.body)
2129
- results = json['results']
2130
- mm = []
2106
+ if height > width
2107
+ min_height = (width * min_crop_ratio).to_i
2108
+ new_height = rand(min_height..width)
2109
+ crop_top = ((height - new_height) / 2.0).round
2131
2110
 
2132
- results.each do |photo|
2133
- full_url = photo.dig('urls', 'full').to_s
2134
- regular_url = photo.dig('urls', 'regular').to_s
2111
+ cropped = img.crop(0, crop_top, width, new_height, true)
2112
+ cropped.write(path)
2135
2113
 
2136
- if full_url.start_with?("https://images.unsplash.com/photo-") &&
2137
- regular_url.include?("1080")
2138
- mm << full_url
2139
- end
2140
- end
2114
+
2115
+ else
2116
+
2117
+ end
2118
+ end
2141
2119
 
2142
- if mm.empty?
2143
- raise "No matching image"
2144
- end
2120
+ def auto_image(keyword = nil)
2121
+ # auto_image 내부에서만 crop 호출
2122
+ keyword ||= @keyword
2123
+ puts "키워드: #{keyword}"
2124
+
2125
+ client = HTTPClient.new
2126
+ client.default_header = {
2127
+ 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
2128
+ '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
2129
+ 'Accept' => 'application/json, text/javascript, */*; q=0.01',
2130
+ 'Accept-Language' => 'en-US,en;q=0.9',
2131
+ 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
2132
+ 'X-Requested-With' => 'XMLHttpRequest'
2133
+ }
2134
+
2135
+ retry_count = 0
2136
+ max_retries = 10
2137
+ results = []
2138
+
2139
+ begin
2140
+ page = rand(1..15)
2141
+ url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
2142
+ puts "Request URL: #{url}"
2143
+ res = client.get(url)
2144
+
2145
+ unless res.status == 200
2146
+ puts "HTTP Error: #{res.status}"
2147
+ raise "HTTP Error"
2148
+ end
2145
2149
 
2146
- selected_url = mm.sample
2147
- Down.download(selected_url, destination: "./image/memory.png")
2148
- puts "이미지 다운로드 완료: #{selected_url}"
2150
+ json = JSON.parse(res.body)
2151
+ results = json['results']
2152
+ mm = []
2149
2153
 
2150
- rescue => e
2151
- retry_count += 1
2152
- puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
2153
- sleep(3)
2154
- if retry_count < max_retries
2155
- retry
2156
- else
2157
- puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
2158
-
2159
- if results && !results.empty?
2160
- random_photo = results.sample
2161
- fallback_url = random_photo.dig('urls', 'full')
2162
- if fallback_url
2163
- Down.download(fallback_url, destination: "./image/memory.png")
2164
- puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
2165
- else
2166
- puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
2167
- color_image
2168
- end
2154
+ results.each do |photo|
2155
+ full_url = photo.dig('urls', 'full').to_s
2156
+ regular_url = photo.dig('urls', 'regular').to_s
2157
+
2158
+ if full_url.start_with?("https://images.unsplash.com/photo-") &&
2159
+ regular_url.include?("1080")
2160
+ mm << full_url
2161
+ end
2162
+ end
2163
+
2164
+ if mm.empty?
2165
+ raise "No matching image"
2166
+ end
2167
+
2168
+ selected_url = mm.sample
2169
+ destination_path = "./image/memory.png"
2170
+ Down.download(selected_url, destination: destination_path)
2171
+ puts "이미지 다운로드 완료: #{selected_url}"
2172
+
2173
+ # 오직 auto_image에서만 자르기 호출
2174
+ crop_image_height_under_width(destination_path)
2175
+
2176
+ rescue => e
2177
+ retry_count += 1
2178
+ puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
2179
+ sleep(3)
2180
+ if retry_count < max_retries
2181
+ retry
2182
+ else
2183
+ puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
2184
+
2185
+ if results && !results.empty?
2186
+ random_photo = results.sample
2187
+ fallback_url = random_photo.dig('urls', 'full')
2188
+ if fallback_url
2189
+ Down.download(fallback_url, destination: "./image/memory.png")
2190
+ puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
2191
+ crop_image_height_under_width("./image/memory.png")
2169
2192
  else
2170
- puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2171
- color_image
2172
- end
2193
+ puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
2194
+ color_image
2173
2195
  end
2196
+ else
2197
+ puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2198
+ color_image
2199
+ end
2174
2200
  end
2175
2201
  end
2202
+ end
2203
+
2176
2204
 
2177
2205
  def color_image
2178
2206
  color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
@@ -2266,57 +2294,104 @@ class Wordpress
2266
2294
  end
2267
2295
 
2268
2296
 
2269
- def image_text(text1, text2)
2297
+ def image_text(text1, text2)
2298
+ begin
2299
+ color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
2300
+ font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
2301
+ font2 = './fonts/' + font_files.sample
2302
+
2303
+ # 랜덤 글자색 선택
2304
+ color2 = color.sample
2305
+
2306
+ # 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
2307
+ def hex_to_rgb(hex)
2308
+ hex = hex.delete('#')
2309
+ [hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
2310
+ end
2311
+
2312
+ # 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
2313
+ def color_distance(c1, c2)
2314
+ Math.sqrt(
2315
+ (c1[0] - c2[0])**2 +
2316
+ (c1[1] - c2[1])**2 +
2317
+ (c1[2] - c2[2])**2
2318
+ )
2319
+ end
2320
+
2321
+ # 대비가 충분히 되는 테두리 색상 선택
2322
+ max_attempts = 10
2323
+ stroke_color = nil
2324
+ base_rgb = hex_to_rgb(color2)
2325
+
2326
+ max_attempts.times do
2327
+ candidate = color.sample
2328
+ candidate_rgb = hex_to_rgb(candidate)
2329
+ dist = color_distance(base_rgb, candidate_rgb)
2330
+
2331
+ # 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
2332
+ if dist > 100
2333
+ stroke_color = candidate
2334
+ break
2335
+ end
2336
+ end
2337
+ stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
2338
+
2339
+ img = Magick::Image.read('./image/memory.png').first
2340
+ draw = Magick::Draw.new
2341
+
2342
+ raw_message = "#{text1}\n#{text2}".strip
2343
+ max_width = img.columns * 0.85
2344
+ max_height = img.rows * 0.6
2345
+
2270
2346
  begin
2271
- color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
2272
- font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
2273
- font2 = './fonts/' + font_files.sample
2274
- color2 = color.sample
2275
-
2276
- img = Magick::Image.read('./image/memory.png').first
2277
- draw = Magick::Draw.new
2278
-
2279
- raw_message = "#{text1}\n#{text2}".strip
2280
- max_width = img.columns * 0.85
2281
- max_height = img.rows * 0.6
2282
-
2283
- begin
2284
- size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
2285
- rescue
2286
- size = 30
2287
- end
2288
-
2289
- wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
2290
-
2291
- if @data['이미지설정']['글자그림자'].checked?
2292
- img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
2293
- draw.gravity = Magick::CenterGravity
2294
- draw.pointsize = adjusted_size
2295
- draw.fill = '#000000'
2296
- draw.font = font2
2297
- end
2298
- end
2299
-
2300
- draw2 = Magick::Draw.new
2301
- img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
2302
- draw2.gravity = Magick::CenterGravity
2303
- draw2.pointsize = adjusted_size
2304
- draw2.fill = color2
2305
- draw2.font = font2
2306
- if @data['이미지설정']['글자테두리'].checked?
2307
- draw2.stroke_width = 2
2308
- draw2.stroke = '#000000'
2309
- end
2310
- end
2311
-
2312
- img.write('./image/memory.png')
2347
+ size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
2313
2348
  rescue
2314
- puts '이미지 폰트 불러오기 오류 재시도...'
2315
- sleep(3)
2316
- retry
2349
+ size = 30
2350
+ end
2351
+
2352
+ wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
2353
+
2354
+ if @data['이미지설정']['글자그림자'].checked?
2355
+ img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
2356
+ draw.gravity = Magick::CenterGravity
2357
+ draw.pointsize = adjusted_size
2358
+ draw.fill = '#000000'
2359
+ draw.font = font2
2360
+ end
2361
+ end
2362
+
2363
+ if @data['이미지설정']['글자테두리'].checked?
2364
+ draw_stroke = Magick::Draw.new
2365
+ img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
2366
+ draw_stroke.gravity = Magick::CenterGravity
2367
+ draw_stroke.pointsize = adjusted_size
2368
+ draw_stroke.fill = 'none'
2369
+ draw_stroke.stroke = stroke_color
2370
+ draw_stroke.stroke_width = rand(5..10)
2371
+ draw_stroke.font = font2
2372
+ end
2317
2373
  end
2374
+
2375
+ draw2 = Magick::Draw.new
2376
+ img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
2377
+ draw2.gravity = Magick::CenterGravity
2378
+ draw2.pointsize = adjusted_size
2379
+ draw2.fill = color2
2380
+ draw2.stroke = 'none'
2381
+ draw2.font = font2
2382
+ end
2383
+
2384
+ img.write('./image/memory.png')
2385
+
2386
+ rescue => e
2387
+ puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
2388
+ sleep(3)
2389
+ retry
2390
+ end
2318
2391
  end
2319
2392
 
2393
+
2394
+
2320
2395
  def border()
2321
2396
  color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
2322
2397
  img = Magick::Image.read('./image/memory.png').first
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cafe_basics_duo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.51
4
+ version: 0.1.52
5
5
  platform: ruby
6
6
  authors:
7
7
  - zon
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-06-25 00:00:00.000000000 Z
10
+ date: 2025-06-26 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: File to Clipboard gem
13
13
  email: mymin26@naver.com