SaveImage SUB: Difference between revisions

From QB64 Phoenix Edition Wiki
Jump to navigation Jump to search
(Created page with "---- ---- <center>'''{{Text|Attention!! - This page is outdated and provided for reference and/or education only.|red}}'''</center> <center>(Return to historic Table of Contents)</center> ---- <center>Starting with '''QB64-PE v3.9.0''' the functionality described here was superseded by _SAVEIMAGE.</center> ---- ----<br> <center>The '''SaveImage SUB''' program to create Bitmaps of other type Images or Screenshots</center> <center>'''Bitmaps'''...")
 
No edit summary
 
(5 intermediate revisions by the same user not shown)
Line 15: Line 15:
* Bitmaps can be 1, 4, 8 or 24/32 bits per pixel(BPP) color palettes. QB64 is capable of working with high color bitmaps.
* Bitmaps can be 1, 4, 8 or 24/32 bits per pixel(BPP) color palettes. QB64 is capable of working with high color bitmaps.
* Screen or Image width and height calculations are automatically made using the image handle value.
* Screen or Image width and height calculations are automatically made using the image handle value.
* Use an image handle value of 0(zero) to get a screen shot of the entire active program screen.
* Use an image handle value of ''zero(0)'' to get a screen shot of the entire active program screen.
* '''Note:''' SCREEN 0 text mode cannot be screen saved in QBasic or QB64 using this SUB.
* '''Note:''' SCREEN 0 text mode cannot be screen saved in QBasic or QB64 using this SUB.




{{PageExamples}}
{{PageExamples}}
; Example: *The following example uses the SaveImage SUB program to save a loaded 32 bit JPEG image as a bitmap using QB64's graphic functions.
;* Example: Using the SaveImage SUB program to save a loaded 32 bit PNG image as a bitmap (BMP) using QB64's graphic functions.
: *Change the _LOADIMAGE filename to an image file you can access.
{{CodeStart}}
{{CodeStart}}
i& = {{Cl|_LOADIMAGE}}("nice.jpg",32) ' loads a 32 bit .JPG file image
{{Text|<nowiki>'load a 32 bit .PNG file image</nowiki>|#919191}}
SaveImage i&, "nice"      'saves it as .BMP file "nice.bmp"
i& = {{Cl|_LOADIMAGE}}({{Text|<nowiki>"source\peLogo.png"</nowiki>|#FFB100}}, {{Text|32|#F580B1}})
'SaveImage 0, "screenshot" 'saves entire program screen as "screenshot.bmp"
{{Cl|IF}} i& < {{Text|-1|#F580B1}} {{Cl|THEN}}
    {{Text|<nowiki>'load success: get image's width/height</nowiki>|#919191}}
    w& = {{Cl|_WIDTH (function)|_WIDTH}}(i&): h& = {{Cl|_HEIGHT}}(i&)
    {{Text|<nowiki>'TEST-1: directly save the loaded image as .BMP file "logo.bmp"</nowiki>|#919191}}
    {{Text|SaveImage|#55FF55}} i&, {{Text|<nowiki>"logo"</nowiki>|#FFB100}}
    {{Text|<nowiki>'TEST-2: make a new 4:3 program SCREEN of the loaded image's width/height</nowiki>|#919191}}
    {{Cl|SCREEN}} {{Cl|_NEWIMAGE}}(({{Text|4|#F580B1}} * w&), ({{Text|3|#F580B1}} * h&), {{Text|32|#F580B1}})
    {{Text|<nowiki>'now tile-fill the screen with the loaded image</nowiki>|#919191}}
    {{Cl|FOR}} x& = {{Text|0|#F580B1}} {{Cl|TO}} ({{Text|4|#F580B1}} * w&) {{Cl|STEP}} w&
        {{Cl|FOR}} y& = {{Text|0|#F580B1}} {{Cl|TO}} ({{Text|3|#F580B1}} * h&) {{Cl|STEP}} h&
            {{Cl|_PUTIMAGE}} (x&, y&), i&
        {{Cl|NEXT}} y&
    {{Cl|NEXT}} x&
    {{Text|<nowiki>'and then save the entire program screen as "screenshot.bmp"</nowiki>|#919191}}
    {{Text|SaveImage|#55FF55}} {{Text|0|#F580B1}}, {{Text|<nowiki>"screenshot"</nowiki>|#FFB100}}
{{Cl|ELSE}}
    {{Text|<nowiki>'load failure: print error</nowiki>|#919191}}
    {{Cl|PRINT}} {{Text|<nowiki>"Cannot find/load the given image."</nowiki>|#FFB100}}
{{Cl|END IF}}
{{Cl|END}}
{{Cl|END}}


{{Cl|SUB}} SaveImage (image {{Cl|AS}} {{Cl|LONG}}, filename {{Cl|AS}} {{Cl|STRING}})
{{Cl|SUB}} {{Text|SaveImage|#55FF55}} (image {{Cl|AS}} {{Cl|LONG}}, filename {{Cl|AS}} {{Cl|STRING}})
bytesperpixel& = {{Cl|_PIXELSIZE}}(image&)
bytesperpixel& = {{Cl|_PIXELSIZE}}(image&)
{{Cl|IF}} bytesperpixel& = 0 {{Cl|THEN}} {{Cl|PRINT}} "Text modes unsupported!": {{Cl|END}}
{{Cl|IF}} bytesperpixel& = {{Text|0|#F580B1}} {{Cl|THEN}} {{Cl|PRINT}} {{Text|<nowiki>"Text modes unsupported!"</nowiki>|#FFB100}}: {{Cl|END}}
{{Cl|IF}} bytesperpixel& = 1 {{Cl|THEN}} bpp& = 8 {{Cl|ELSE}} bpp& = 24
{{Cl|IF}} bytesperpixel& = {{Text|1|#F580B1}} {{Cl|THEN}} bpp& = {{Text|8|#F580B1}} {{Cl|ELSE}} bpp& = {{Text|24|#F580B1}}
x& = {{Cl|_WIDTH (function)|_WIDTH}}(image&)
x& = {{Cl|_WIDTH (function)|_WIDTH}}(image&)
y& = {{Cl|_HEIGHT}}(image&)
y& = {{Cl|_HEIGHT}}(image&)
b$="BM????QB64????"+{{Cl|MKL$}}(40)+{{Cl|MKL$}}(x&)+{{Cl|MKL$}}(y&)+{{Cl|MKI$}}(1)+{{Cl|MKI$}}(bpp&)+{{Cl|MKL$}}(0)+"????"+{{Cl|STRING$}}(16, 0) 'partial BMP header info(???? to be filled later)
b$ = {{Text|<nowiki>"BM????QB64????"</nowiki>|#FFB100}} + {{Cl|MKL$}}({{Text|40|#F580B1}}) + {{Cl|MKL$}}(x&) + {{Cl|MKL$}}(y&) + {{Cl|MKI$}}({{Text|1|#F580B1}}) + {{Cl|MKI$}}(bpp&) + {{Cl|MKL$}}({{Text|0|#F580B1}}) + {{Text|<nowiki>"????"</nowiki>|#FFB100}} + {{Cl|STRING$}}({{Text|16|#F580B1}}, {{Text|0|#F580B1}}) {{Text|<nowiki>'partial BMP header info(???? to be filled later)</nowiki>|#919191}}
{{Cl|IF}} bytesperpixel& = 1 {{Cl|THEN}}
{{Cl|IF}} bytesperpixel& = {{Text|1|#F580B1}} {{Cl|THEN}}
  {{Cl|FOR...NEXT|FOR}} c& = 0 {{Cl|TO}} 255 ' read BGR color settings from JPG image + 1 byte spacer({{Cl|CHR$}}(0))
    {{Cl|FOR}} c& = {{Text|0|#F580B1}} {{Cl|TO}} {{Text|255|#F580B1}} {{Text|<nowiki>' read BGR color settings from JPG image + 1 byte spacer(CHR$(0))</nowiki>|#919191}}
    cv& = {{Cl|_PALETTECOLOR (function)|_PALETTECOLOR}}(c&, image&) ' color attribute to read.
        cv& = {{Cl|_PALETTECOLOR (function)|_PALETTECOLOR}}(c&, image&) {{Text|<nowiki>' color attribute to read.</nowiki>|#919191}}
    b$ = b$ +{{Cl|CHR$}}({{Cl|_BLUE32}}(cv&))+{{Cl|CHR$}}({{Cl|_GREEN32}}(cv&))+{{Cl|CHR$}}({{Cl|_RED32}}(cv&))+{{Cl|CHR$}}(0) 'spacer byte
        b$ = b$ + {{Cl|CHR$}}({{Cl|_BLUE32}}(cv&)) + {{Cl|CHR$}}({{Cl|_GREEN32}}(cv&)) + {{Cl|CHR$}}({{Cl|_RED32}}(cv&)) + {{Cl|CHR$}}({{Text|0|#F580B1}}) {{Text|<nowiki>'spacer byte</nowiki>|#919191}}
  {{Cl|NEXT}}
    {{Cl|NEXT}}
{{Cl|END IF}}
{{Cl|END IF}}
{{Cl|MID$}}(b$, 11, 4) = {{Cl|MKL$}}({{Cl|LEN}}(b$)) ' image pixel data offset(BMP header)
{{Cl|MID$}}(b$, {{Text|11|#F580B1}}, {{Text|4|#F580B1}}) = {{Cl|MKL$}}({{Cl|LEN}}(b$)) {{Text|<nowiki>' image pixel data offset(BMP header)</nowiki>|#919191}}
lastsource& = {{Cl|_SOURCE}}
lastsource& = {{Cl|_SOURCE (function)|_SOURCE}}
{{Cl|_SOURCE}} image&
{{Cl|_SOURCE}} image&
{{Cl|IF}} ((x& * 3) {{Cl|MOD}} 4) {{Cl|THEN}} padder$ = {{Cl|STRING$}}(4 - ((x& * 3) {{Cl|MOD}} 4), 0)
{{Cl|IF}} ((x& * {{Text|3|#F580B1}}) {{Cl|MOD}} {{Text|4|#F580B1}}) {{Cl|THEN}} padder$ = {{Cl|STRING$}}({{Text|4|#F580B1}} - ((x& * {{Text|3|#F580B1}}) {{Cl|MOD}} {{Text|4|#F580B1}}), {{Text|0|#F580B1}})
{{Cl|FOR...NEXT|FOR}} py& = y& - 1 {{Cl|TO}} 0 {{Cl|STEP}} -1 ' read JPG image pixel color data
{{Cl|FOR}} py& = y& - {{Text|1|#F580B1}} {{Cl|TO}} {{Text|0|#F580B1}} {{Cl|STEP}} {{Text|-1|#F580B1}} {{Text|<nowiki>' read JPG image pixel color data</nowiki>|#919191}}
  r$ = ""
    r$ = {{Text|<nowiki>""</nowiki>|#FFB100}}
  {{Cl|FOR...NEXT|FOR}} px& = 0 {{Cl|TO}} x& - 1
    {{Cl|FOR}} px& = {{Text|0|#F580B1}} {{Cl|TO}} x& - {{Text|1|#F580B1}}
  c& = {{Cl|POINT}}(px&, py&) 'POINT 32 bit values are large {{Cl|LONG}} values
        c& = {{Cl|POINT}}(px&, py&) {{Text|<nowiki>'POINT 32 bit values are large LONG values</nowiki>|#919191}}
  {{Cl|IF}} bytesperpixel& = 1 {{Cl|THEN}} r$ = r$ + {{Cl|CHR$}}(c&) {{Cl|ELSE}} r$ = r$ + {{Cl|LEFT$}}({{Cl|MKL$}}(c&), 3)
        {{Cl|IF}} bytesperpixel& = {{Text|1|#F580B1}} {{Cl|THEN}} r$ = r$ + {{Cl|CHR$}}(c&) {{Cl|ELSE}} r$ = r$ + {{Cl|LEFT$}}({{Cl|MKL$}}(c&), {{Text|3|#F580B1}})
  {{Cl|NEXT}} px&
    {{Cl|NEXT}} px&
  d$ = d$ + r$ + padder$
    d$ = d$ + r$ + padder$
{{Cl|NEXT}} py&
{{Cl|NEXT}} py&
{{Cl|_SOURCE}} lastsource&
{{Cl|_SOURCE}} lastsource&
{{Cl|MID$}}(b$, 35, 4) = {{Cl|MKL$}}({{Cl|LEN}}(d$)) ' image size(BMP header)
{{Cl|MID$}}(b$, {{Text|35|#F580B1}}, {{Text|4|#F580B1}}) = {{Cl|MKL$}}({{Cl|LEN}}(d$)) {{Text|<nowiki>' image size(BMP header)</nowiki>|#919191}}
b$ = b$ + d$ ' total file data bytes to create file
b$ = b$ + d$ {{Text|<nowiki>' total file data bytes to create file</nowiki>|#919191}}
{{Cl|MID$}}(b$, 3, 4) = {{Cl|MKL$}}({{Cl|LEN}}(b$)) ' size of data file(BMP header)
{{Cl|MID$}}(b$, {{Text|3|#F580B1}}, {{Text|4|#F580B1}}) = {{Cl|MKL$}}({{Cl|LEN}}(b$)) {{Text|<nowiki>' size of data file(BMP header)</nowiki>|#919191}}
{{Cl|IF}} {{Cl|LCASE$}}({{Cl|RIGHT$}}(filename$, 4)) <> ".bmp" {{Cl|THEN}} ext$ = ".bmp"
{{Cl|IF}} {{Cl|LCASE$}}({{Cl|RIGHT$}}(filename$, {{Text|4|#F580B1}})) <> {{Text|<nowiki>".bmp"</nowiki>|#FFB100}} {{Cl|THEN}} ext$ = {{Text|<nowiki>".bmp"</nowiki>|#FFB100}}
f& = {{Cl|FREEFILE}}
f& = {{Cl|FREEFILE}}
{{Cl|OPEN}} filename$ + ext$ {{Cl|FOR (file statement)|FOR}} {{Cl|OUTPUT}} {{Cl|AS}} #f&: {{Cl|CLOSE}} #f& ' erases an existing file
{{Cl|OPEN}} filename$ + ext$ {{Cl|OPEN#File_Access_Modes|FOR}} {{Cl|OPEN#File_Access_Modes|OUTPUT}} {{Cl|OPEN|AS}} #f&: {{Cl|CLOSE}} #f& {{Text|<nowiki>' erases an existing file</nowiki>|#919191}}
{{Cl|OPEN}} filename$ + ext$ {{Cl|FOR (file statement)|FOR}} {{Cl|BINARY}} {{Cl|AS}} #f&
{{Cl|OPEN}} filename$ + ext$ {{Cl|OPEN#File_Access_Modes|FOR}} {{Cl|OPEN#File_Access_Modes|BINARY}} {{Cl|OPEN|AS}} #f&
{{Cl|PUT}} #f&,,b$
{{Cl|PUT}} #f&, , b$
{{Cl|CLOSE}} #f&
{{Cl|CLOSE}} #f&
{{Cl|END SUB}}
{{Cl|END SUB}}
Line 68: Line 85:




'''SUB Explanation:''' b$ and d$ assemble the entire string of data to create a bitmap file. Some of the bitmap header info is placed later using a [[MID$ (statement)]] to add final header numerical data converted to [[ASCII]] characters by [[MKI$]] or [[MKL$]].
'''SUB Explanation:''' b$ and d$ assemble the entire string of data to create a bitmap file. Some of the bitmap header info is placed later using a [[MID$]] to add final header numerical data converted to [[ASCII]] characters by [[MKI$]] or [[MKL$]].


After the header, the [[RGB]] color settings are created using [[ASCII]] characters read backwards as Blue, Green, Red and CHR$(0) as a spacer. [[MKL$]] places the byte values in reverse order too. Bitmaps and icons require that format. [[LEFT$]] trims off the [[_ALPHA]] byte.
After the header, the [[RGB]] color settings are created using [[ASCII]] characters read backwards as Blue, Green, Red and CHR$(0) as a spacer. [[MKL$]] places the byte values in reverse order too. Bitmaps and icons require that format. [[LEFT$]] trims off the [[_ALPHA]] byte.
Line 79: Line 96:
{{PageSeeAlso}}
{{PageSeeAlso}}
* [[_LOADIMAGE]], [[_ICON]], [[$EXEICON]]
* [[_LOADIMAGE]], [[_ICON]], [[$EXEICON]]
* [[SCREEN (statement)]]
* [[SCREEN]]
* [[TYPE]], [[MKI$]], [[MKL$]]
* [[TYPE]], [[MKI$]], [[MKL$]]
* [[Program ScreenShots]] {{text|(member SUB program)}}
* [[Program ScreenShots]] {{text|(member SUB program)}}

Latest revision as of 00:35, 18 November 2024



Attention!! - This page is outdated and provided for reference and/or education only.
(Return to historic Table of Contents)

Starting with QB64-PE v3.9.0 the functionality described here was superseded by _SAVEIMAGE.



The SaveImage SUB program to create Bitmaps of other type Images or Screenshots
Bitmaps are image files with the .BMP file name extension.


  • Bitmaps can be 1, 4, 8 or 24/32 bits per pixel(BPP) color palettes. QB64 is capable of working with high color bitmaps.
  • Screen or Image width and height calculations are automatically made using the image handle value.
  • Use an image handle value of zero(0) to get a screen shot of the entire active program screen.
  • Note: SCREEN 0 text mode cannot be screen saved in QBasic or QB64 using this SUB.


Examples

Example
  • Using the SaveImage SUB program to save a loaded 32 bit PNG image as a bitmap (BMP) using QB64's graphic functions.
'load a 32 bit .PNG file image
i& = _LOADIMAGE("source\peLogo.png", 32)
IF i& < -1 THEN
    'load success: get image's width/height
    w& = _WIDTH(i&): h& = _HEIGHT(i&)
    'TEST-1: directly save the loaded image as .BMP file "logo.bmp"
    SaveImage i&, "logo"
    'TEST-2: make a new 4:3 program SCREEN of the loaded image's width/height
    SCREEN _NEWIMAGE((4 * w&), (3 * h&), 32)
    'now tile-fill the screen with the loaded image
    FOR x& = 0 TO (4 * w&) STEP w&
        FOR y& = 0 TO (3 * h&) STEP h&
            _PUTIMAGE (x&, y&), i&
        NEXT y&
    NEXT x&
    'and then save the entire program screen as "screenshot.bmp"
    SaveImage 0, "screenshot"
ELSE
    'load failure: print error
    PRINT "Cannot find/load the given image."
END IF
END

SUB SaveImage (image AS LONG, filename AS STRING)
bytesperpixel& = _PIXELSIZE(image&)
IF bytesperpixel& = 0 THEN PRINT "Text modes unsupported!": END
IF bytesperpixel& = 1 THEN bpp& = 8 ELSE bpp& = 24
x& = _WIDTH(image&)
y& = _HEIGHT(image&)
b$ = "BM????QB64????" + MKL$(40) + MKL$(x&) + MKL$(y&) + MKI$(1) + MKI$(bpp&) + MKL$(0) + "????" + STRING$(16, 0) 'partial BMP header info(???? to be filled later)
IF bytesperpixel& = 1 THEN
    FOR c& = 0 TO 255 ' read BGR color settings from JPG image + 1 byte spacer(CHR$(0))
        cv& = _PALETTECOLOR(c&, image&) ' color attribute to read.
        b$ = b$ + CHR$(_BLUE32(cv&)) + CHR$(_GREEN32(cv&)) + CHR$(_RED32(cv&)) + CHR$(0) 'spacer byte
    NEXT
END IF
MID$(b$, 11, 4) = MKL$(LEN(b$)) ' image pixel data offset(BMP header)
lastsource& = _SOURCE
_SOURCE image&
IF ((x& * 3) MOD 4) THEN padder$ = STRING$(4 - ((x& * 3) MOD 4), 0)
FOR py& = y& - 1 TO 0 STEP -1 ' read JPG image pixel color data
    r$ = ""
    FOR px& = 0 TO x& - 1
        c& = POINT(px&, py&) 'POINT 32 bit values are large LONG values
        IF bytesperpixel& = 1 THEN r$ = r$ + CHR$(c&) ELSE r$ = r$ + LEFT$(MKL$(c&), 3)
    NEXT px&
    d$ = d$ + r$ + padder$
NEXT py&
_SOURCE lastsource&
MID$(b$, 35, 4) = MKL$(LEN(d$)) ' image size(BMP header)
b$ = b$ + d$ ' total file data bytes to create file
MID$(b$, 3, 4) = MKL$(LEN(b$)) ' size of data file(BMP header)
IF LCASE$(RIGHT$(filename$, 4)) <> ".bmp" THEN ext$ = ".bmp"
f& = FREEFILE
OPEN filename$ + ext$ FOR OUTPUT AS #f&: CLOSE #f& ' erases an existing file
OPEN filename$ + ext$ FOR BINARY AS #f&
PUT #f&, , b$
CLOSE #f&
END SUB
Code by Galleon


SUB Explanation: b$ and d$ assemble the entire string of data to create a bitmap file. Some of the bitmap header info is placed later using a MID$ to add final header numerical data converted to ASCII characters by MKI$ or MKL$.

After the header, the RGB color settings are created using ASCII characters read backwards as Blue, Green, Red and CHR$(0) as a spacer. MKL$ places the byte values in reverse order too. Bitmaps and icons require that format. LEFT$ trims off the _ALPHA byte.

The actual image is read as pixel attributes from the image bottom to the top for proper formatting with zero padding when necessary.

Note: 32-bit images will be saved as 24-bit BMP files. All palette indexed images/modes will be saved as 256 color BMP files. Text modes cannot be saved.


See also



Navigation:
Main Page with Articles and Tutorials
Keyword Reference - Alphabetical
Keyword Reference - By usage
Report a broken link