Announcement

Collapse
No announcement yet.

Easiest way to convert a JPG to a DIB (BMP file) in memory?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Elias Montoya
    replied
    Originally posted by Anthony Watson View Post
    ...not rely on the work of others. That's why I got into programming in the first place....
    Sometimes that is nearly impossible. Examples are a very important part on
    the learning. As brad points out, this code is based on Semen's iPicture,
    without it, it would be very hard to learn about that.

    But cheer up, the PB comunity is full of helping hands.

    Leave a comment:


  • Anthony Watson
    replied
    Brad,

    No problem, I understand being busy... The code Elias provided is serving my needs well.

    Regarding the palettes, I did some quick searching this morning here and on Google, and think I have found the information I need to build the color table.

    Elias,

    While I try to avoid external support files in general, I just prefer to know how and why things are functioning in my programs and not rely on the work of others. That's why I got into programming in the first place.

    I really don't do much work with graphics, so GDI+ is probably overkill for my situation. But I'll keep it in mind if my needs change.

    Thanks,

    Anthony

    Leave a comment:


  • Elias Montoya
    replied
    I suggest you to listen to Brad's advice. Having dependency on a DLL is
    a low price you have to pay compared to all the functionality you can get
    from it. Specially when GDI+ is free.

    Leave a comment:


  • Brad D Byrne
    replied
    Anthony, I need to stop promising to do things, I simply have very little time right now, and all my PB code is on another machine, but it appears that Elias has provided some good help!

    his code is based on Semen's iPicture code if your interested,

    also, you really might want to look into the GDI+ stuff it does a lot more!

    about palettes, there was an old thread here that very extensively explained the "palette table"/s, as well as a different Bmp2Gif solution - B

    Leave a comment:


  • Anthony Watson
    replied
    Elias,

    I don't really need PNG support for my application, I just thought I'd ask.

    My application is now loading JPG's fine, but I have run into a couple of issues.

    It appears the code you supplied results in an image with a 32-bit color depth. This wouldn't be a problem for viewing, but I need to load and save the image in a database. A 16 color BMP or a 256 color GIF file ends up being huge once loaded.

    I thought I'd work around that problem and tackle my resizing needs at once by creating a bitmap in memory and stretchblt'ing from one bitmap to the other. This works great to get down to 16-bit or 24-bit DIB's, but I've run into a problem if I try reducing it further to 256 colors or less. I can't figure out how to get a color table when reducing it to 256 colors. No matter what I do, the RGBQUAD data is zero.

    Here's a clip from my program. I don't know how understandable it will be without all the subroutines it relies on, but hopefully you can get the basic idea of what I'm doing.

    Code:
            '** Get bitmap dimensions
            a=GetObject(hBitmap,SIZEOF(bm),bm)
            old_wide=bm.bmwidth
            old_high=bm.bmheight
            bpp=bm.bmbitspixel
            old_sz=bm.bmheight*bm.bmwidthbytes
    
            '** Scale image down if too large
            new_wide=old_wide
            new_high=old_high
            IF new_wide>640 OR new_high>480 THEN
              a#=480/new_high
              b#=640/new_wide
              IF a#>b# THEN
                a#=b#
              END IF
              new_wide=new_wide*a#
              new_high=new_high*a#
            END IF
    
            '** Define the new bitmap
            new_bpp=16
            rgb_size=0
            IF new_bpp<16 THEN
              rgb_size=(2^new_bpp)*4   '** 1, 16, or 256 color
            END IF
    
            '** Create a header for the new bitmap
            CALL create_buffer(40+rgb_size,bitmap_header)
            CALL memfill(bitmap_header,0,40+rgb_size,0)
            CALL put_long(bitmap_header,0,40)
            CALL put_long(bitmap_header,4,new_wide)
            CALL put_long(bitmap_header,8,new_high)
            CALL put_word(bitmap_header,12,1)
            CALL put_word(bitmap_header,14,new_bpp)
            CALL put_long(bitmap_header,16,%BI_RGB)
    
            '** Create the bitmap
            temp_bmp=CreateDIBSection(screen,BYVAL bitmap_header,%DIB_RGB_COLORS,BYVAL VARPTR(ppvBits),0,0)
    
            '** Set Device Contexts and copy old bitmap to new one
            src_dc=CreateCompatibleDC(screen)
            src_old=SelectObject(src_dc,hBitmap)
            dst_dc=CreateCompatibleDC(screen)
            dst_old=SelectObject(dst_dc,temp_bmp)
            CALL SetStretchBltMode(dst_dc,%COLORONCOLOR)
            CALL StretchBlt(dst_dc,0,0,new_wide,new_high,src_dc,0,0,old_wide,old_high,%SRCCOPY)
    
            '** Get the color table for the bitmap
            IF rgb_size>0 THEN
              CALL create_buffer(rgb_size,color_table)
              a=GetDibColorTable(dst_dc,0,rgb_size/4,BYVAL color_table)
            END IF
    
            CALL SelectObject(src_dc,src_old)
            CALL SelectObject(dst_dc,dst_old)
            CALL DeleteDC(src_dc)
            CALL DeleteDC(dst_dc)
    
            '** Get the data bits for the bitmap
            a=GetObject(temp_bmp,SIZEOF(bm),bm)
            data_size=bm.bmheight*bm.bmwidthbytes
    
            '** Create memory buffer for the new bitmap
            bmp_size=54+rgb_size+data_size
            CALL create_buffer(bmp_size,address)
            CALL memfill(address,0,bmp_size,0)
    
            '** Set the file header
            CALL put_word(address,0,CVI("BM"))
            CALL put_long(address,2,bmp_size)
            CALL put_long(address,10,bmp_size-data_size)  '** start of bitmap data
    
            '** Copy bitmap header
            CALL bmove(bitmap_header,0,address,14,40)
    
            '** Copy the color table
            CALL bmove(color_table,0,address,54,rgb_size)
    
            '** Get the bitmap data
            di=getdibits(screen,temp_bmp,0,new_high,BYVAL address+54+rgb_size,BYVAL bitmap_header,%DIB_RGB_COLORS)
    
            CALL free_buffer(bitmap_header)
            CALL free_buffer(color_table)
    
            CALL DeleteObject(temp_bmp)
            CALL DeleteObject(hBitmap)
    From what I could make out on MSDN, the CreateDIBSection should create the palette table itself? But it doesn't, even though everything else works fine.

    I tried calling the GetDIBColorTable to get the RGB palette, but while the call returns successfully with no errors, the color table is still zero'd out.

    What am I missing?

    For now I'll make do with 16-bit bitmaps, and loading smaller BMP files directly (bypassing your code). But it would be nice to get the GIF's down to 256 color bitmaps since that's all they have to start with.

    Thanks,

    Anthony

    Leave a comment:


  • Elias Montoya
    replied
    Originally posted by Anthony Watson View Post
    ...Is there any way to get it to load PNG files as well (now I'm just being greedy... )?
    Unfortunately, Not without the need of third party dll's (as far as i know).
    I think you will need GDI+ for this one.

    Leave a comment:


  • Anthony Watson
    replied
    Elias,

    With a little modification your sample appears to be working perfectly in my program. Thank you!

    One question though, it appears to load JPG, BMP, and GIF files without difficulty. Is there any way to get it to load PNG files as well (now I'm just being greedy... )?

    Very much appreciated!

    Anthony

    Leave a comment:


  • Anthony Watson
    replied
    Brad,

    Yep, I discovered the muldiv API on MSDN shortly after posting my message. Figures...

    I look forward to seeing your sample...

    Elias,

    Thanks for the sample code. It looks closer to what I'm needing, so I'll examine it in more detail this afternoon when I can find the time. Thanks!

    Anthony

    Leave a comment:


  • Elias Montoya
    replied
    Convert JPG to BITMAP from memory

    This is (somewhat) the code i use in Egrid32. PLease test it toroughly
    because i didnt tested it much after i extracted it from it (i removed a
    bunch of features from the Egrid32 library and i dont know if this example
    has something broken). No reading from file is strictly required, i just used the
    read thing to make the example.

    Step 1: Read the image from file, but it can be read from anywhere.

    Step 2: Convert the JPG to a bitmap handle IN MEMORY. No writing to file.

    I left some resizing features that Egrid32 uses.

    Code:
    #INCLUDE "WIN32API.INC"
    
    $IMAGEFILE  = "C:\foto.jpg"    '<------------------CHANGE TO YOUR PIC
    
    TYPE IPicture DWORD
      QueryInterface   AS DWORD
      AddRef           AS DWORD
      Release          AS DWORD
      get_Handle       AS DWORD
      get_Hpal         AS DWORD
      get_Type         AS DWORD
      get_Width        AS DWORD
      get_Height       AS DWORD
      RENDER           AS DWORD
      set_Hpal         AS DWORD
      get_CurDC        AS DWORD
      SelectPicture    AS DWORD
      get_KeepOriginal AS DWORD
      put_KeepOriginal AS DWORD
      PictureChanged   AS DWORD
      SaveAsFile       AS DWORD
      get_Attributes   AS DWORD
    END TYPE 'IPicture
    
    TYPE IStream DWORD
      QueryInterface  AS DWORD
      AddRef          AS DWORD
      Release         AS DWORD
      SRead           AS DWORD
      SWrite          AS DWORD
      SSeek           AS DWORD
      SetSize         AS DWORD
      CopyTo          AS DWORD
      Commit          AS DWORD
      Revert          AS DWORD
      LockRegion      AS DWORD
      UnlockRegion    AS DWORD
      Stat            AS DWORD
      Clone           AS DWORD
    END TYPE 'IStream
    
    $PicID = CHR$(&H80, &H09, &HF8, &H7B, &H32, &HBF, &H1A, &H10, &H8B, &HBB, &H00, &HAA, &H00, &H30, &H0C, &HAB)
    
    DECLARE FUNCTION RelCall(pStrm AS DWORD) AS DWORD
    DECLARE FUNCTION CreateStreamOnHGlobal LIB "Ole32.dll" ALIAS "CreateStreamOnHGlobal" _
                     (hGlobalMem AS DWORD, DelOnRel AS DWORD, pStrm AS DWORD) AS DWORD
    DECLARE FUNCTION OleLoadPicture LIB "Olepro32.dll" ALIAS "OleLoadPicture" _
                     (BYVAL pStream AS DWORD, BYVAL PicSz AS DWORD, BYVAL fRunmode AS DWORD, _
                     pPicID AS ASCIZ * 17, ppvObj AS DWORD) AS DWORD
    DECLARE FUNCTION RendCall(hDC AS DWORD, x AS DWORD, y AS DWORD, cx AS DWORD, _
                     cy AS DWORD, nul AS DWORD, pic_height AS DWORD, pic_width _
                     AS DWORD, pic_height AS DWORD, nul AS DWORD, rct AS ANY) AS DWORD
    DECLARE FUNCTION DimenCall(pIStrmPtr AS DWORD, PicDimen AS DWORD) AS DWORD
    
    
    FUNCTION Load_ImageFromMemory(ImagePtr AS DWORD, ImageSize AS DWORD, Xsize AS LONG, YSize AS LONG, KeepRatio AS LONG) AS DWORD
    
    LOCAL hFile       AS DWORD        'picture's file handle
    LOCAL hMem        AS DWORD        'handle to globally alocated memory
    LOCAL pMem        AS DWORD        'pointer to globally alocated memory
    LOCAL a           AS DWORD
    LOCAL HDC         AS DWORD
    LOCAL DDC         AS DWORD
    LOCAL HBMP        AS DWORD
    LOCAL HBM         AS DWORD
    LOCAL rct         AS Rect
    LOCAL pIStrmPtr   AS IStream PTR  'ptr to IStream interface ptr
    LOCAL pIPicPtr    AS IPicture PTR 'ptr to IPicture interface ptr
    LOCAL PicWd       AS DWORD        'picture's HIMETRIC width
    LOCAL PicHt       AS DWORD        'picture's HIMETRIC height
    LOCAL PicWdPix    AS DWORD        'picture's width in pixels
    LOCAL PicHtPix    AS DWORD        'picture's height in pixels
    LOCAL DX          AS SINGLE
    LOCAL DY          AS SINGLE
    LOCAL PicSz       AS DWORD        'size of picture file in bytes
    LOCAL DataCorrect AS DWORD
    LOCAL Imagestring AS STRING
    
     IF Xsize < 0 THEN Xsize = 0
     IF Ysize < 0 THEN Ysize = 0
    
     IF ISTRUE(ImagePtr) AND ISTRUE(ImageSize) THEN
      ImageString = PEEK$(ImagePtr, ImageSize)
      hMem = GlobalAlloc(%GMEM_MOVEABLE, LEN(ImageString))
      IF hMem THEN
       pMem = GlobalLock(hMem)
       POKE$ pMem, ImageString
       DataCorrect = %TRUE
      END IF
     ELSE
      EXIT FUNCTION
     END IF
      
     IF ISTRUE(pMem) AND ISTRUE(DataCorrect) THEN
      IF (CreateStreamOnHGlobal(BYVAL hMem, BYVAL 1&, BYREF pIStrmPtr)) THEN EXIT IF
      IF OleLoadPicture(pIStrmPtr, PicSz, 0&,BYREF $PicID, pIPicPtr) THEN EXIT IF
      CALL DWORD @@pIStrmPtr.Release USING RelCall(BYVAL pIStrmPtr)
      CALL DWORD @@pIPicPtr.Get_Width USING DimenCall(BYVAL pIPicPtr,BYREF PicWd)
      CALL DWORD @@pIPicPtr.Get_Height USING DimenCall(BYVAL pIPicPtr,BYREF PicHt)
      DDC = GetDC(%HWND_DESKTOP)
       PicWdPix = CDBL((PicWd * GetDeviceCaps(DDC, %LOGPIXELSX)) / 2540)
       PicHtPix = CDBL((PicHt * GetDeviceCaps(DDC, %LOGPIXELSY)) / 2540)
       IF ISTRUE(Xsize) AND ISTRUE(ISTRUE(Ysize)) THEN
        IF KeepRatio THEN
         DX = (PicWdPix/Xsize)
         DY = (PicHtPix/Ysize)
         IF (DX > DY) THEN
          PicWdPix = (PicWdPix/DX)
          PicHtPix = (PicHtPix/DX)
         ELSE
          PicWdPix = (PicWdPix/DY)
          PicHtPix = (PicHtPix/DY)
         END IF
        ELSE
         PicWdPix = Xsize
         PicHtPix = Ysize
        END IF
       END IF
       HDC  = CreateCompatibleDC(DDC)
       HBMP = CreateCompatibleBitmap(DDC, PicWdPix, PicHtPix)
       IF GetStretchBltMode(HDC) <> %STRETCH_HALFTONE THEN
        CALL SetStretchBltMode(HDC, %STRETCH_HALFTONE)
        CALL SetBrushOrgEx(HDC, 0, 0, BYVAL %Null)
       END IF
       HBM  = SelectObject(HDC, HBMP)
       CALL ReleaseDC(%HWND_DESKTOP, DDC)
       SetRect RCT, 1, 1, PicWdPix, PicHtPix
       CALL DWORD @@pIPicPtr.Render USING RendCall(BYVAL pIPicPtr, BYVAL HDC, _
            BYVAL 0, BYVAL 0, BYVAL PicWdPix, BYVAL PicHtPix, BYVAL 0&, BYVAL PicHt, BYVAL PicWd,  _
            BYVAL -PicHt, BYVAL VARPTR(rct))
       CALL DWORD @@pIPicPtr.Release USING RelCall(BYVAL pIPicPtr)
       SelectObject HDC, HBM
       DeleteDC HDC
      FUNCTION = HBMP
      IF pMem  THEN CALL GlobalUnlock(hMem)
      IF hMem  THEN CALL GlobalFree(Hmem)
     END IF
    
    END FUNCTION
    
    
    
    FUNCTION PBMAIN AS LONG
    
    LOCAL ImageContents AS STRING
    LOCAL hBitmap AS DWORD
    LOCAL FF AS LONG
    
    ' get the image fom file.
    FF = FREEFILE
    OPEN $IMAGEFILE FOR BINARY AS #FF
     ImageContents = SPACE$(LOF(FF))
     GET #ff,,ImageContents
    CLOSE #FF
    
        
        
    ' Convert JPG to Bitmap from memory
    hBitmap = Load_ImageFromMemory(STRPTR(ImageContents), LEN(ImageContents), 0, 0, 0)
    
    IF HBitmap THEN
     MSGBOX "Success. Bitmap Handle is: " & STR$(hBitmap)
     DeleteObject hBitmap
    ELSE
     MSGBOX "Failure, Check JPG file."
    END IF
        
    END FUNCTION
    Last edited by Elias Montoya; 20 Mar 2008, 04:28 PM.

    Leave a comment:


  • Brad D Byrne
    replied
    Anthony,


    MulDiv is an API function,

    The MulDiv function multiplies two 32-bit values and then divides the 64-bit result by a third 32-bit value. The return value is rounded up or down to the nearest integer.

    http://msdn2.microsoft.com/en-us/lib...18(VS.85).aspx

    I'm still using PBWin ver 7.2, (been primarily learning web stuff so I havn't upgraded yet) so I'm not sure why the examples don't run ?

    but, I know what you are after, I'll put together a sample sometime tonight

    Leave a comment:


  • Anthony Watson
    replied
    Brad,

    I spent the day searching through the OLE picture viewers in the forums. Unfortunately, the samples I found wouldn't copy into PowerBASIC and run correctly. Don't know if the forum corrupted them or what, but with a bit cleaning and reediting, I have a couple of working samples.

    Unfortunately, I don't really understand what is taking place, so I'm still trying to figure out how I would get a bitmap handle that I could use for blitting and other purposes in my software.

    While studying the example source codes, I ran across what I believe is a command called "muldiv"? It's not listed anywhere in the PowerBASIC documentation, but it's used in many programs here on the forum. What is "muldiv" and what does it do? Is there a modern equivalent command?

    Thanks,

    Anthony

    Leave a comment:


  • Brad D Byrne
    replied
    Anthony, when you load any image into a DIB, the DIB is in a BMP format, so then all you have to do is save the DIB and conversion is done for you,

    search for "OLE Picture Viewer" for ways to load the DIB, and then "Save Bitmap" for the save code,there's tons of examples here

    Leave a comment:


  • Easiest way to convert a JPG to a DIB (BMP file) in memory?

    I've searched through the forums, but haven't really found what I'm looking for.

    Basically, I need to convert a JPG file that has been loaded into a memory buffer (the entire file, copied to a buffer in memory) into a DIB bitmap I can use for various purposes.

    I would prefer a solution that doesn't require an external DLL of any type, works with Win98 and up, and can be used freely (no restrictions on distribution).

    I've seen bits and pieces of GDI+ code that "seems" like it would do what I need, but I'd really like to see a full standalone sample source code if possible.

    Thanks,

    Anthony
Working...
X