質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

1回答

381閲覧

VB.NET用でC++のDLL作成ですがpicturebox間で高速な拡大縮小を知っていましたら教えてください。

littlestream

総合スコア36

VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2024/01/16 14:22

実現したいこと

現在自分はVB.NETにおいて、ペイントソフトを作っているのですが
CでDLLを作ってまでpictureboxAからpictureboxBへ高速な拡大縮小コピーもしくは、
picBackのバックバッファにMouseMoveイベントを起こして
picFrontに拡大表示したいのですが、

調べ方が甘いのか高速な拡大縮小コピーのやり方が
よくわからないです。なぜかというと、ネットで調べるとvb.netで拡縮処理をする際の情報にほとんど
必ず何故か既存の画像をpictureboxに開いて拡大縮小コピー処理しているからです。

つまり、自分のやりたい拡縮処理は既に描画メソッドを使って描画済みのpictureboxに
拡大縮小コピーしたいのですが自分の不得意なc++&WINAPIでDLLを作ってまでプログラム作成するか
考え中です。

もしもDLLを作ってしまわなくとも同様の拡縮処理が行えるやり方の方法が
知っていましたら教えてください。ちなみに相当な数のページをブックマークしましたが

StrectchBltやDrawImage、キャプチャー、保存、どれもうまくいきませんでした。
あと、Ctrl+F5を押すと何故かエラーになるのにF5を押すとプログラムが起動します。
これは何かの例外処理エラーなのか分かりません。

発生している問題・分からないこと

描画最中のpicBackからpicFrontへpictureAの内容を高速で拡大コピーしたいのに
全く表示されません。どうすれば高速な拡大縮小コピーが出来るか教えてください。

該当のソースコード

VB.NET

1Private Sub ButtonKake_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonKake.Click 2 Dim R As Integer 3 Dim G As Integer 4 Dim B As Integer 5 6 scaleX *= 2 7 Dim bmp As Bitmap = New Bitmap(PicBack.Width, PicBack.Height) 8 Dim bmpFront As Bitmap = New Bitmap(PicFront.Width, PicFront.Height) 9 Dim liner As New Pen(Color.FromArgb(PalColor(PalNum).R * 32, PalColor(PalNum).G * 32, PalColor(PalNum).B * 32), 1) 10 '描画先とするImageオブジェクトを作成する 11 Dim canvas As New Bitmap(PicFront.Width, PicFront.Height) 12 'ImageオブジェクトのGraphicsオブジェクトを作成する 13 Dim g2 As Graphics = Graphics.FromImage(canvas) 14 15 For Y = 0 To PicBack.Height 16 For X = 0 To PicBack.Width 17 R = bmp.GetPixel(X / scaleX, Y / scaleX).R 18 G = bmp.GetPixel(X / scaleX, Y / scaleX).G 19 B = bmp.GetPixel(X / scaleX, Y / scaleX).B 20 21 22 '(10, 20)-(100, 200)に、幅1の黒い線を引く 23 g2.DrawLine(liner, X, Y, X, Y) 24 25 Next 26 Next 27 'リソースを解放する 28 g2.Dispose() 29 'PictureBox1に表示する 30 PicFront.Image = canvas 31 32 End Sub 33 34続いてDLL作成中cコード 35#include<windows.h> 36#include "main.h" 37 38#pragma once 39#define DLLEXPORT extern "C" __declspec(dllexport) 40DLLEXPORT void Init8BitDIB(int Width,int Height,LPBYTE lpDIB,LPBYTE lpPixel,LPBITMAPINFO lpbiInfo, 41 LPRGBQUAD lpRGB); 42DLLEXPORT void SetPallet(int Index,int R,int G,int B,LPRGBQUAD lpRGB); 43DLLEXPORT void PSET(int x,int y,int Width,int Index,LPBYTE lpPixel); 44 45↑main.h 46 47↓main.cpp 48DLLEXPORT void Init8BitDIB(int Width,int Height,LPBYTE lpDIB,LPBYTE lpPixel,LPBITMAPINFO lpbiInfo, 49 LPRGBQUAD lpRGB) { 50 int i; 51 52 /* DIB用バッファ確保 */ 53 lpDIB = (LPBYTE)HeapAlloc(GetProcessHeap(), 54 HEAP_ZERO_MEMORY, sizeof(BITMAPINFO) + 55 255 * sizeof(RGBQUAD) + 128 * 256); 56 57 /* ポインタ設定 */ 58 lpbiInfo = (LPBITMAPINFO)lpDIB; 59 lpPixel = lpDIB + sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD); 60 lpRGB = (LPRGBQUAD)(lpbiInfo->bmiColors); 61 62 /* 適当なカラーテーブルを設定 */ 63 for (i = 0;i < 256;i++) { 64 65 lpRGB[i].rgbRed = i; 66 lpRGB[i].rgbGreen = 255 - i; 67 lpRGB[i].rgbBlue = 128 - i / 2; 68 69 } 70 71 /* BITMAPINFO設定 */ 72 lpbiInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 73 lpbiInfo->bmiHeader.biWidth = 128; 74 lpbiInfo->bmiHeader.biHeight = 256; 75 lpbiInfo->bmiHeader.biPlanes = 1; 76 lpbiInfo->bmiHeader.biBitCount = 8; 77 lpbiInfo->bmiHeader.biCompression = BI_RGB; 78 79 /* 適当なピクセル列を設定 */ 80 for (i = 0;i < 256;i++) { 81 FillMemory(lpPixel + i * 128, 128, i); 82 } 83 84 return; 85 86} 87 88 89DLLEXPORT void SetPallet(int Index,int R,int G,int B,LPRGBQUAD lpRGB) 90{ 91 if(Index<1 || Index>255) return; 92 93 lpRGB[Index].rgbRed=R; 94 lpRGB[Index].rgbGreen=G; 95 lpRGB[Index].rgbBlue=B; 96 97 return; 98} 99 100DLLEXPORT void PSET(int x,int y,int Width,int Index,LPBYTE lpPixel) 101{ 102 lpPixel[x+y*Width]=Index; 103 return; 104}

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

VBNETの自作なんちゃってパレットは動きますが、
picbackにマウスカーソルを動かしても全く変化が無い
ばかりかpicbackに表示されているかどうかは未確認ですがpicFrontには表示されないです。
ただし、picFrontを取り除くとpicbackには等倍で表示されます。

補足

開発環境Windows11 home SDD256GB Memory 16GB CPU:AMD
VisualBasic.NET 2008 Expressです。
(もし仮に作る必要ならば)DLL作成はVisualC++6.0です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YAmaGNZ

2024/01/17 01:04

提示されているコードは線を描画しているだけに見えるのですが抜粋部分を間違えていたりしますか? 質問文内にPicBack、PicFront、pictureboxA、pictureboxBと別物と思われるものが出てきますし、C++のDLLの話もありますが提示されているVB側のコードに呼び出している部分はなさそうですし 「picbackにマウスカーソルを動かしても全く変化が無い」とありますが、提示部分にはマウスカーソルの移動に関するイベントは処理していませんし、申し訳ありませんが何をどうしたいのか問題点はどこなのか私には正確に理解できませんでした。 PicFrontに拡大鏡のようにPicBackに表示されている画像の一部分(マウスカーソルの部分)を表示したいが現状の方法(コードがないのでどのような方法か分かりませんが)だと遅いから高速化したいということですか?
YAmaGNZ

2024/01/17 06:29

投稿時にチャタったのか同じ質問がいくつか作成されていますので削除申請するなり対応されたほうがよろしいかと思います。
littlestream

2024/01/17 07:07

https://www.google.com/search?q=teratail+%E8%B3%AA%E5%95%8F+%E5%89%8A%E9%99%A4&oq=teratail+%E8%B3%AA%E5%95%8F%E3%80%80%E5%89%8A%E9%99%A4&gs_lcrp=EgZjaHJvbWUyCQgAEEUYORiABDIGCAEQRRhA0gELNDIzMDI2ajFqMTWoAgCwAgA&sourceid=chrome&ie=UTF-8 で質問の削除方法を調べたのですが、質問ページの削除リクエストボタンがページ内を文字検索しても 普通にページ内を見渡しても見つからないのとteratialを原則として質問の削除を受け付けていないらしいので難しいかもしれません。
guest

回答1

0

ベストアンサー

下の例は picBack に表示されている内容を picFront へ2倍に拡大して表示するサンプルです。
参考になるでしょうか?

vb

1Imports System.Runtime.InteropServices 2 3Public Class Form1 4 5 Private Const SRCCOPY As Integer = &HCC0020 6 7 <DllImport("gdi32.dll")> 8 Private Shared Function StretchBlt( _ 9 hdcDest As IntPtr, xDest As Integer, yDest As Integer, wDest As Integer, hDest As Integer, _ 10 hdcSrc As IntPtr, xSrc As Integer, ySrc As Integer, wSrc As Integer, hSrc As Integer, _ 11 dwRop As Integer) As Boolean 12 End Function 13 14 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 15 Dim zoom As Single = 2.0F 16 Dim buffer As New Bitmap(picFront.ClientSize.Width, picFront.ClientSize.Height) 17 Dim srcSize As Size = picBack.ClientSize 18 Dim dstSize As New Size(CInt(srcSize.Width * zoom), CInt(srcSize.Height * zoom)) 19 Using src As Graphics = picBack.CreateGraphics(), 20 dst As Graphics = Graphics.FromImage(buffer) 21 Dim srcHdc As IntPtr = src.GetHdc() 22 Dim dstHdc As IntPtr = dst.GetHdc() 23 StretchBlt(dstHdc, 0, 0, dstSize.Width, dstSize.Height, 24 srcHdc, 0, 0, srcSize.Width, srcSize.Height, SRCCOPY) 25 src.ReleaseHdc() 26 dst.ReleaseHdc() 27 End Using 28 Dim oldImage As Image = picFront.Image 29 If oldImage IsNot Nothing Then 30 oldImage.Dispose() 31 End If 32 picFront.Image = buffer 33 End Sub 34 35End Class

投稿2024/01/17 00:59

KOZ6.0

総合スコア2628

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

littlestream

2024/01/17 02:10

ありがとうございます!! 今日は会社なので、すみませんが、 自宅に帰宅してソースを実行してから返信しますね。
littlestream

2024/01/17 10:31

さきほど帰宅しました。早速ソースを実行したのですが、やはり うまく行かなかったです。真っ黒なピクチャーボックスのままでした。 さきほどのソースに何か書き間違えがないか探してみたのですが、いくつか見つかりましたが そのソースの中の改行に"_"文字で修正したソースでもやはりさきほどと変わりなかったです。 なので誠に申し訳ないですが、下記のリンク先のソースを参考にさせていただきました。 https://hanatyan.sakura.ne.jp/vb2005/vb2013picturebox01.htm#no2 ありがとうございました。 ただ、気になるのはこのまま拡大縮小しても、 8BitDIBのようなピクセル中の画素のパレット番号を変更しても 何も変わらない事です。なのでどちらにしてもこれはパレットを扱うソフトとしては 問題があるかもしれませんが、その質問は自力でgoogleなどの検索エンジンで調べて答えが出なかったら また質問させてもらいます。 KOZ6.0さん、長文ありがとうございました。
KOZ6.0

2024/01/17 11:09

>うまく行かなかったです。真っ黒なピクチャーボックスのままでした。 picBack が非表示になってませんか? >ピクセル中の画素のパレット番号を変更しても フルカラーだとパレットを持たないので 256色以下の Bitmap を作成し、Palette プロパティで得られる ColorPalette クラスオブジェクトを操作することになります。 「C#でBitmapのパレットを更新する」 https://araramistudio.jimdo.com/2016/10/17/bitmap%E3%81%AE%E3%83%91%E3%83%AC%E3%83%83%E3%83%88%E3%82%92%E6%9B%B4%E6%96%B0%E3%81%99%E3%82%8B/ もしくは、ColorMatrix を使って色変更することになると思います。 「画像のカラーバランスを補正して表示する」 https://dobon.net/vb/dotnet/graphics/colorbalance.html
littlestream

2024/01/17 12:46

コメントありがとうございます! 実はここの部分って本当にDlllImportできてるのかな?って実はありました。 それが以下です。 DllImport("gdi32.dll") ???ココです。 Private Shared Function StretchBlt(ByVal ... ここをうまく書き換えて以下のようにしたら上手く拡大してくれました。 速度も今のところ問題ないと思います。 <DllImport("gdi32.dll")> _ ???ここの←の"_"です。 Private Shared Function StretchBlt(ByVal ... あとは、Timer1プロパティをEnable=trueにすれば定期的に ミリ秒単位でうまく処理してくれると思います。
littlestream

2024/01/17 12:47

まだKOZ6.0さんのコメントを読んでみてすぐに行動に移って成功したのでパレットに 関してはあとで返信する予定です。わざわざすみません。
littlestream

2024/01/18 09:14

すみません、リンク先のソースを見ても何が何だかすぐに理解できていない状態なので 一日過ぎましたが、また機会を見て質問します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問