News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Looking for a JPEG library

Started by NoCforMe, November 09, 2018, 05:35:35 PM

Previous topic - Next topic

aw27

In my whole life I don't remember ever finding an undocumented Windows bug, it was always a bug in my own code.  :(

Vortex

mabdelouahab's application works fine both on Windows XP 32-bit and Windows PE based on XP 32-bit.

jj2007

#17
Quote from: mabdelouahab on November 13, 2018, 03:57:20 AMLet's find out what's wrong with you.

Nothing is wrong with me, mabdelouahab. And I use a much more sophisticated gdi+ error checking.

Fact is that
a) your executable gets refused by my Win32 XP VM, which may simply be a manifest problem
b) I can re-build it, and then it runs on my VM
c) my executable runs fine on various configurations
d) but it crashes without warning and without errors in exactly one configuration: the normal execution on Win XP 8)

EDIT: I found the culprit:
GetEncoderCLSID proc uses esi edi ebx fileW$
LOCAL extW, encNum, encSize, pImageCodecInfo, mimeBuffer[32]:BYTE, encBuffer[8000]:BYTE ; typical size is 1040 bytes
  mov edi, fileW$
  push edi
  call MbStrLenW
  lea edi, [edi+2*eax]
:badgrin:

aw27

So, it is a bug in your masm basic code, not a mysterious Windows bug.

jj2007

I know I shouldn't feed the troll, but actually, where did I write it was a Windows bug?

NoCforMe

Quote from: hutch-- on November 10, 2018, 07:32:46 PM
I hate to have to tell you this [...]
No you don't, but let's continue:
Quotebut your forum name "NoCforMe" is probably the main obstruction to you getting what you are after. People who write many different computer languages all have to deal with an OS that is written primarily in C and while in this case, assemblers deal with C formats just fine, if you shut the door on C you have shut the door on much of what the OS has to offer.

Since you brought this up, I'm going to reply to you. So when I posted a perfectly valid, reasonable question here about programming, you chose to scold me for my choice of usernames, rather than help me. Really? Does my name really bug you all that much? My, you must be pretty thin-skinned to get up on your high horse like that. (Besides which, I actually did get a bunch of helpful replies, in spite of my stupid username!)

Look: I don't like to use C, for my own projects. I'm not working in production, making stuff that will be sold into the marketplace. It's strictly for my own amusement. I prefer plain old MASM, the tools which you offer here. I don't even like to use macros for the most part. Just my taste is all. And I've got absolutely nothing against anyone else using any damn language they please to program. Hell, I've coded COBOL in a past life (and as a side note, it was exactly the right tool for the job, for payroll and accounting applications). So please don't lecture me about my "handle".

QuoteYou could look at GDIPLUS for at least some of what you are after but appreciate that there is no easy path to get what you are after.
Now that is actually potentially helpful to me. See my next posting below here.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Now I'm thinking about using GDI+. But first I've got to understand it a bit better.

Let's take opening a JPEG image from a file and displaying it. Reading MSDN, it appears I first need to use the Bitmap method to obtain the image (see here), then use the Graphics method to display it (see here). Fine. But I'm really confused by the Graphics stuff. Assuming I need to use the Graphics:DrawImage method, that page shows more than a dozen of them. Which one do I use?

MASM32 appears to have GDI+ support baked into it, but I'm confused about how to use it since it doesn't seem to be documented anywhere that I can see. Looking at gdiplus.inc, I see a dozen prototypes for GdipDrawImageXXXX, where XXXX is I, PointRect, PointRectI, Points, etc. Where do I find descriptions of these functions so I can use them.?

And is it really as easy as that, calling Bitmap:Bitmap, then Graphics:DrawImage?

As I said, all I really want to do at this point is open a JPEG and display it, optionally resize it, and save it back to disk.

I assume I can use something like StretchBlt() to resize an image?

Thanks in advance for any help!
Assembly language programming should be fun. That's why I do it.

hutch--

 :biggrin:

Here is the problem, generally people who jump up on their high horse tend to fall off the other side and land on their arse. When you take the disposition that you exclude the sum total of C based API code, you are asking other people to translate it for you which is an unreasonable demand. We all have to suffer lousy Microsoft documentation and most have been doing it for years.

The old GDI does many things OK, its not fast enough for animation or gaming but more than capable for presentation graphics. At best GDI+ is very badly documented and Microsoft only support high level wrappers in C++. The best reference material that is easily available was written by Jose Roca in PowerBASIC.

You are basically stuck with the same irritation that the rest of us are, lousy documentation and the need for "some C for Me".

NoCforMe

Quote from: hutch-- on December 05, 2018, 11:40:33 AM
:biggrin:
You are basically stuck with the same irritation that the rest of us are, lousy documentation and the need for "some C for Me".
OK, I get it. But I figure that since those functions (C++ "methods" that have been given library names) are in your (MASM32's) library, they must be usable, right? Is there any way to figure out which is which, what parameters these functions take? Otherwise why would you have bothered to include them in the first place?

If there's some other library out there that would do the simple things I'm after I'd be happy to use it. So far none of the suggestions given in this thread have proven usable to me (some were 64-bit, others didn't have the functionality I needed). So I'll wait here patiently ...
Assembly language programming should be fun. That's why I do it.

NoCforMe

Quote from: hutch-- on December 05, 2018, 11:40:33 AM
The old GDI does many things OK, its not fast enough for animation or gaming but more than capable for presentation graphics.
Except that plain old GDI doesn't have any built-in support for JPEG, right?
Assembly language programming should be fun. That's why I do it.

hutch--

> So I'll wait here patiently ...

That will not get you anywhere. Like the rest of us you have to go look for it yourself. Asking for a jpg library is assuming there is one for you to use and that may not be the case. I did suggest that you try GDI+ but I warned you that the documentation is very bad. I downloaded an old PLATFORMSDK dated about 2006 to try and get better reference but it was no better than Jose Roca's basic help file.

I have a little GDI+ done in 64 bit but only for loading image files, mainly for toolbars and background images, I have not decyphered writing a bitmap image back to disk as a jpg.

NoCforMe

Maybe this will help. I stumbled upon this page at Microsoft's Reference Source, which I didn't even know existed. There I found the following somewhat self-documenting prototypes for all 12 of the GdipDrawImageXXXX() functions:
internal static extern int GdipDrawImage(HandleRef graphics, HandleRef image, float x, float y);
internal static extern int GdipDrawImageI(HandleRef graphics, HandleRef image, int x, int y);
internal static extern int GdipDrawImageRect(HandleRef graphics, HandleRef image, float x,
float y, float width, float height);
internal static extern int GdipDrawImageRectI(HandleRef graphics, HandleRef image, int x,
int y, int width, int height);
internal static extern int GdipDrawImagePoints(HandleRef graphics, HandleRef image,
HandleRef points, int count);
internal static extern int GdipDrawImagePointsI(HandleRef graphics, HandleRef image,
HandleRef points, int count);
internal static extern int GdipDrawImagePointRect(HandleRef graphics, HandleRef image, float x,
float y, float srcx, float srcy,
float srcwidth, float srcheight,
int srcunit);
internal static extern int GdipDrawImagePointRectI(HandleRef graphics, HandleRef image, int x,
int y, int srcx, int srcy,
int srcwidth, int srcheight,
int srcunit);
internal static extern int GdipDrawImageRectRect(HandleRef graphics, HandleRef image,
float dstx, float dsty,
float dstwidth, float dstheight,
float srcx, float srcy,
float srcwidth, float srcheight,
int srcunit, HandleRef imageAttributes,
Graphics.DrawImageAbort callback, HandleRef callbackdata);
internal static extern int GdipDrawImageRectRectI(HandleRef graphics, HandleRef image,
int dstx, int dsty,
int dstwidth, int dstheight,
int srcx, int srcy,
int srcwidth, int srcheight,
int srcunit, HandleRef imageAttributes,
Graphics.DrawImageAbort callback, HandleRef callbackdata);
internal static extern int GdipDrawImagePointsRect(HandleRef graphics, HandleRef image,
HandleRef points, int count, float srcx,
float srcy, float srcwidth,
float srcheight, int srcunit,
HandleRef imageAttributes,
Graphics.DrawImageAbort callback, HandleRef callbackdata);
internal static extern int GdipDrawImagePointsRectI(HandleRef graphics, HandleRef image,
HandleRef points, int count, int srcx,
int srcy, int srcwidth,
int srcheight, int srcunit,
HandleRef imageAttributes,
Graphics.DrawImageAbort callback, HandleRef callbackdata);

Now we know that the "I" functions use integer arguments while the others use floats. Still leaves some mysteries to clear up, like that first parameter, HandleRef graphics. How do I get that handle? Apparently it's not just a DC like you'd use with GDI. If I could figure that out I could start displaying images with GDI+.

[Breaking News] Just found this in MS ref.source:
internal static extern int GdipCreateFromHDC(HandleRef hdc, out IntPtr graphics);
So it looks like I pass it in an hDC and a pointer to a "graphics" (it's a DWORD, who cares?), then pass "graphics" to DrawImage(). I think I'll try it.
Assembly language programming should be fun. That's why I do it.

NoCforMe

  :t
Well, I got it to work. Code posted below, zip file includes the image whose name is hard-coded.

It works, but not the way it should. Question: Why is the image so much smaller than full size? Someone's doing some kind of scaling here. Further experimentation needed ...


;============================================
; -- JPEG testbed, using GDI+ --
;
;============================================


include \masm32\include\masm32rt.inc
include \masm32\include\gdiplus.inc
includelib \masm32\lib\gdiplus.lib


;============================================
; Defines, macros, prototypes, etc.
;============================================

WinMain PROTO :DWORD

$mainWinWidth EQU 600
$mainWinHeight EQU 500

;===== Window styles: =====
$mainWinStyles EQU WS_OVERLAPPEDWINDOW OR WS_CLIPCHILDREN OR WS_VISIBLE

;===== Window background colors: =====
$bkRED EQU 254
$bkGRN EQU 243
$bkBLUE EQU 199

$BkColor EQU $bkRED OR ($bkGRN SHL 8) OR ($bkBLUE SHL 16)

;============================================
; HERE BE DATA
;============================================
.data

WC WNDCLASSEX < SIZEOF WNDCLASSEX, \
CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW, \
NULL, \ ;lpfnWndProc
NULL, \ ;cbClsExtra
NULL, \ ;cbWndExtra
NULL, \ ;hInstance
NULL, \ ;hIcon
NULL, \ ;hCursor
NULL, \ ;hbrBackground
NULL, \ ;lpszMenuName
NULL, \ ;lpszClassName
NULL > ;hIconSm


GDIinputStruct GdiplusStartupInput <1, NULL, FALSE, 0>

MainClassName DB "JPEGtest", 0
MainTitleText DB "JPEG Testbed", 0

; Name is in Unicode:
JPEGfilename DB 't', 0, 'e', 0, 's', 0, 't', 0, '.', 0, 'j', 0, 'p', 0, 'g', 0, 0


;============================================
; UNINITIALIZED DATA
;============================================
.data?

MainWinHandle HWND ?

GDItoken DD ?


;============================================
; CODE LIVES HERE
;============================================
.code


start: INVOKE GetModuleHandle, NULL
MOV WC.hInstance, EAX

INVOKE WinMain, EAX
INVOKE ExitProcess, EAX


;====================================================================
; Mainline proc
;====================================================================

WinMain PROC hInst:DWORD
LOCAL msg:MSG, brush:HBRUSH, wX:DWORD, wY:DWORD, gpRect:RECT


; Create  brush to set background color:
INVOKE CreateSolidBrush, $BkColor
MOV brush, EAX

; Register class for parent window:
MOV WC.lpfnWndProc, OFFSET MainWindowProc
MOV EAX, brush
MOV WC.hbrBackground, EAX
MOV WC.lpszClassName, OFFSET MainClassName
MOV WC.hIcon, NULL
INVOKE LoadCursor, NULL, IDC_ARROW
MOV WC.hCursor, EAX
INVOKE RegisterClassEx, OFFSET WC

INVOKE GetSystemMetrics, SM_CXSCREEN
MOV EDX, $mainWinWidth
CALL CenterDim
MOV wX, EAX
INVOKE GetSystemMetrics, SM_CYSCREEN
MOV EDX, $mainWinHeight
CALL CenterDim
MOV wY, EAX

; Create our main window:
INVOKE CreateWindowEx, WS_EX_OVERLAPPEDWINDOW, OFFSET MainClassName,
OFFSET MainTitleText, $mainWinStyles, wX, wY, $mainWinWidth,
$mainWinHeight, NULL, NULL, hInst, NULL
MOV MainWinHandle, EAX

;********  Initialize GDI+:  ********
INVOKE GdiplusStartup, OFFSET GDItoken, OFFSET GDIinputStruct, NULL


;============= Message loop ===================
msgloop:
INVOKE GetMessage, ADDR msg, NULL, 0, 0
OR EAX, EAX ;EAX = 0 = exit
JZ exit99
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
JMP msgloop

exit99: INVOKE GdiplusShutdown, GDItoken
MOV EAX, msg.wParam
RET

WinMain ENDP


;====================================================================
; Main Window Proc
;====================================================================

MainWindowProc PROC hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
LOCAL hDC:HDC, gdiHgraphics:DWORD, gdiHbitmap:DWORD
LOCAL ps:PAINTSTRUCT

MOV EAX, uMsg
CMP EAX, WM_PAINT
JE do_paint
CMP EAX, WM_CLOSE
JE do_close

dodefault:
; use DefWindowProc for all other messages:
INVOKE DefWindowProc, hWin, uMsg, wParam, lParam
RET

do_paint:
INVOKE BeginPaint, hWin, ADDR ps
MOV hDC, EAX

; Open JPEG file:
INVOKE GdipLoadImageFromFile, OFFSET JPEGfilename, ADDR gdiHbitmap

; Get graphics "object" from DC handle:
INVOKE GdipCreateFromHDC, hDC, ADDR gdiHgraphics

; Display image:
INVOKE GdipDrawImageI, gdiHgraphics, gdiHbitmap, 50, 50

INVOKE EndPaint, hWin, ADDR ps
XOR EAX, EAX
RET


do_close:
INVOKE PostQuitMessage, NULL
MOV EAX, TRUE
RET


MainWindowProc ENDP


;====================================================================
; CenterDim
;
; Returns half screen dimension (X or Y) minus half window dimension
;
; On entry,
; EAX = screen dimension
; EDX = window dimension
;
; Returns:
; sdim/2 - wdim/2
;====================================================================

CenterDim PROC

SHR EAX, 1 ;divide screen dimension by 2
SHR EDX, 1 ;divide window dimension by 2
SUB EAX, EDX
RET ;Return w/# in EAX

CenterDim ENDP


END start
Assembly language programming should be fun. That's why I do it.

jj2007

Gdi+ is a little bit old, therefore it is difficult to find good documentation. But if you don't need high speed for games, it is still a very powerful API.

Attached a file that I use for my stuff, containing documentation of 600+ Gdi+ functions. It's RTF, opens best in RichMasm but also in WordPad or MS Word.

Hope it helps, Jochen