Saving a picture in jpeg format (pure FreeBasic, no external libraries)

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
angros47
Posts: 2323
Joined: Jun 21, 2005 19:04

Saving a picture in jpeg format (pure FreeBasic, no external libraries)

Post by angros47 »

This is a port of https://github.com/jpcy/jo_jpeg in FreeBasic:

Code: Select all

declare function jo_write_jpg_to_func(data_ as any ptr, width_ as long, height as long, comp as long, quality as long) as integer


dim shared as ubyte s_jo_ZigZag(...) = {0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }


sub jo_writeBits(byref bitBuf as long, byref bitCnt as long, bs as const unsigned short ptr)
	bitCnt += bs[1]
	bitBuf or= bs[0] shl (24 - bitCnt)
	while(bitCnt >= 8) 
		dim c as ubyte = (bitBuf shr 16) and 255
		put #1,, c
		if c = 255 then print #1,chr(0);
		bitBuf shl= 8
		bitCnt -= 8
	wend
end sub

sub jo_DCT(byref d0 as single, byref d1 as single,  byref d2 as single,  byref d3 as single,  byref d4 as single,  byref d5 as single,  byref d6 as single,  byref d7 as single)
	dim as single tmp0 = d0 + d7
	dim as single tmp7 = d0 - d7
	dim as single tmp1 = d1 + d6
	dim as single tmp6 = d1 - d6
	dim as single tmp2 = d2 + d5
	dim as single tmp5 = d2 - d5
	dim as single tmp3 = d3 + d4
	dim as single tmp4 = d3 - d4

	' Even part
	dim as single tmp10 = tmp0 + tmp3
	dim as single tmp13 = tmp0 - tmp3
	dim as single tmp11 = tmp1 + tmp2
	dim as single tmp12 = tmp1 - tmp2

	d0 = tmp10 + tmp11
	d4 = tmp10 - tmp11

	dim as single z1 = (tmp12 + tmp13) * 0.707106781f
	d2 = tmp13 + z1
	d6 = tmp13 - z1

	tmp10 = tmp4 + tmp5
	tmp11 = tmp5 + tmp6
	tmp12 = tmp6 + tmp7

	dim as single z5 = (tmp10 - tmp12) * 0.382683433f
	dim as single z2 = tmp10 * 0.541196100f + z5
	dim as single z4 = tmp12 * 1.306562965f + z5
	dim as single z3 = tmp11 * 0.707106781f

	dim as single z11 = tmp7 + z3
	dim as single z13 = tmp7 - z3

	d5 = z13 + z2
	d3 = z13 - z2
	d1 = z11 + z4
	d7 = z11 - z4
end sub 

sub jo_calcBits(val_ as long, bits() as unsigned short)
	dim as long tmp1 = abs(val_)
	val_ = iif(val_ < 0 , val_-1 , val_)
	bits(1) = 1
	tmp1 shr=1
	while tmp1
		tmp1 shr=1
		bits(1)+=1
	wend
	bits(0) = val_ and ((1 shl bits(1))-1)
end sub

function jo_processDU(byref bitBuf as long, byref bitCnt as long, CDU() as single, fdtbl() as single, DC as long, HTDC() as const ushort, HTAC() as const ushort) as long
	dim as unsigned short EOB(1) = { HTAC(0,0), HTAC(0,1) }
	dim as unsigned short M16zeroes(1) = { HTAC(&hF0,0), HTAC(&hF0,1) }

	for dataOff as integer=0 to 63 step 8
		jo_DCT(CDU(dataOff), CDU(dataOff+1), CDU(dataOff+2), CDU(dataOff+3), CDU(dataOff+4), CDU(dataOff+5), CDU(dataOff+6), CDU(dataOff+7))
	next

	for dataOff as integer=0 to 7
		jo_DCT(CDU(dataOff), CDU(dataOff+8), CDU(dataOff+16), CDU(dataOff+24), CDU(dataOff+32), CDU(dataOff+40), CDU(dataOff+48), CDU(dataOff+56))
	next

	dim DU(63) as long
	for i as integer=0 to 63
		dim as single v = CDU(i)*fdtbl(i)
		DU(s_jo_ZigZag(i)) =  iif(v < 0 , fix(v - 0.5f), fix(v + 0.5f))
	next

	dim diff as long= DU(0) - DC
	if diff = 0 then
		jo_writeBits(bitBuf, bitCnt, @HTDC(0,0))
	else
		dim as unsigned short bits(1)
		jo_calcBits(diff, bits())
		jo_writeBits(bitBuf, bitCnt, @HTDC(bits(1),0))
		jo_writeBits(bitBuf, bitCnt, @bits(0))
	end if

	dim as long end0pos = 63
	while end0pos>0 andalso DU(end0pos)=0: end0pos-=1:wend

	if end0pos = 0 then
		jo_writeBits(bitBuf, bitCnt, @EOB(0))
		return DU(0)
	end if
	for i as integer = 1 to end0pos
		dim as integer startpos = i
		while DU(i)=0 andalso i<=end0pos: i+=1:wend
		dim as long nrzeroes = i-startpos
		if nrzeroes >= 16 then
			dim as long lng = nrzeroes shr 4
			for nrmarker as long=1 to lng
				jo_writeBits(bitBuf, bitCnt, @M16zeroes(0))
			next
			nrzeroes and= 15
		end if
		dim as unsigned short bits(1)
		jo_calcBits(DU(i), bits())
		jo_writeBits(bitBuf, bitCnt, @HTAC((nrzeroes shl 4)+bits(1),0))
		jo_writeBits(bitBuf, bitCnt, @bits(0))
	next
	if end0pos <> 63 then jo_writeBits(bitBuf, bitCnt, @EOB(0))
	return DU(0)
end function

function jo_write_jpg(filename as string, data_ as any ptr, width_ as long, height as long, comp as long=4, quality as long) as integer
	if filename ="" then return 0

	open filename for binary as #1

	dim as integer result = jo_write_jpg_to_func(data_, width_, height, comp, quality)
	close #1
	return result
end function

function jo_write_jpg_to_func(data_ as any ptr, width_ as long, height as long, comp as long, quality as long) as integer
	static as const ubyte std_dc_luminance_nrcodes(...) = {0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}
	static as const ubyte std_dc_luminance_values(...) = {0,1,2,3,4,5,6,7,8,9,10,11}
	static as const ubyte std_ac_luminance_nrcodes(...) = {0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,&H7d}
	static as const ubyte std_ac_luminance_values(...) = {_
		&H01,&H02,&H03,&H00,&H04,&H11,&H05,&H12,&H21,&H31,&H41,&H06,&H13,&H51,&H61,&H07,&H22,&H71,&H14,&H32,&H81,&H91,&Ha1,&H08,_
		&H23,&H42,&Hb1,&Hc1,&H15,&H52,&Hd1,&Hf0,&H24,&H33,&H62,&H72,&H82,&H09,&H0a,&H16,&H17,&H18,&H19,&H1a,&H25,&H26,&H27,&H28,_
		&H29,&H2a,&H34,&H35,&H36,&H37,&H38,&H39,&H3a,&H43,&H44,&H45,&H46,&H47,&H48,&H49,&H4a,&H53,&H54,&H55,&H56,&H57,&H58,&H59,_
		&H5a,&H63,&H64,&H65,&H66,&H67,&H68,&H69,&H6a,&H73,&H74,&H75,&H76,&H77,&H78,&H79,&H7a,&H83,&H84,&H85,&H86,&H87,&H88,&H89,_
		&H8a,&H92,&H93,&H94,&H95,&H96,&H97,&H98,&H99,&H9a,&Ha2,&Ha3,&Ha4,&Ha5,&Ha6,&Ha7,&Ha8,&Ha9,&Haa,&Hb2,&Hb3,&Hb4,&Hb5,&Hb6,_
		&Hb7,&Hb8,&Hb9,&Hba,&Hc2,&Hc3,&Hc4,&Hc5,&Hc6,&Hc7,&Hc8,&Hc9,&Hca,&Hd2,&Hd3,&Hd4,&Hd5,&Hd6,&Hd7,&Hd8,&Hd9,&Hda,&He1,&He2,_
		&He3,&He4,&He5,&He6,&He7,&He8,&He9,&Hea,&Hf1,&Hf2,&Hf3,&Hf4,&Hf5,&Hf6,&Hf7,&Hf8,&Hf9,&Hfa_
	}
	static as const ubyte std_dc_chrominance_nrcodes(...) = {0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}
	static as const ubyte std_dc_chrominance_values(...) = {0,1,2,3,4,5,6,7,8,9,10,11}
	static as const ubyte std_ac_chrominance_nrcodes(...) = {0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,&H77}
	static as const ubyte std_ac_chrominance_values(...) = {_
		&H00,&H01,&H02,&H03,&H11,&H04,&H05,&H21,&H31,&H06,&H12,&H41,&H51,&H07,&H61,&H71,&H13,&H22,&H32,&H81,&H08,&H14,&H42,&H91,_
		&Ha1,&Hb1,&Hc1,&H09,&H23,&H33,&H52,&Hf0,&H15,&H62,&H72,&Hd1,&H0a,&H16,&H24,&H34,&He1,&H25,&Hf1,&H17,&H18,&H19,&H1a,&H26,_
		&H27,&H28,&H29,&H2a,&H35,&H36,&H37,&H38,&H39,&H3a,&H43,&H44,&H45,&H46,&H47,&H48,&H49,&H4a,&H53,&H54,&H55,&H56,&H57,&H58,_
		&H59,&H5a,&H63,&H64,&H65,&H66,&H67,&H68,&H69,&H6a,&H73,&H74,&H75,&H76,&H77,&H78,&H79,&H7a,&H82,&H83,&H84,&H85,&H86,&H87,_
		&H88,&H89,&H8a,&H92,&H93,&H94,&H95,&H96,&H97,&H98,&H99,&H9a,&Ha2,&Ha3,&Ha4,&Ha5,&Ha6,&Ha7,&Ha8,&Ha9,&Haa,&Hb2,&Hb3,&Hb4,_
		&Hb5,&Hb6,&Hb7,&Hb8,&Hb9,&Hba,&Hc2,&Hc3,&Hc4,&Hc5,&Hc6,&Hc7,&Hc8,&Hc9,&Hca,&Hd2,&Hd3,&Hd4,&Hd5,&Hd6,&Hd7,&Hd8,&Hd9,&Hda,_
		&He2,&He3,&He4,&He5,&He6,&He7,&He8,&He9,&Hea,&Hf2,&Hf3,&Hf4,&Hf5,&Hf6,&Hf7,&Hf8,&Hf9,&Hfa_
	}
	static as const ushort YDC_HT(255,1) = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}
	static as const ushort UVDC_HT(255,1) = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}
	static as const ushort YAC_HT(255,1) = { _
		{10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}_
	}
	static as const ushort UVAC_HT(255,1) = { _
		{0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0},_
		{1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}_
	}
	static as const long YQT(...) = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22,37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}
	static as const long UVQT(...) = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}
	static as const single aasf(...) = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }

	if data_=0 orelse width_=0 orelse height=0 orelse comp > 4 orelse comp < 1 orelse comp = 2 then return 0

	quality = iif(quality, quality, 90)
	quality = iif(quality < 1 , 1 , iif(quality > 100, 100, quality))
	quality = iif(quality < 50, 5000 / quality, 200 - quality * 2)

	dim as ubyte YTable(63), UVTable(63)
	for i as integer = 0 to 63
		dim yti as integer = (YQT(i)*quality+50)/100
		YTable(s_jo_ZigZag(i)) = iif(yti < 1, 1, iif (yti > 255, 255, yti))
		dim uvti as integer = (UVQT(i)*quality+50)/100
		UVTable(s_jo_ZigZag(i)) = iif(uvti < 1, 1, iif(uvti > 255, 255, uvti))
	next

	dim as single fdtbl_Y(63), fdtbl_UV(63)
	dim as integer k
	for row as integer=0 to 7
		for col as integer=0 to 7
			fdtbl_Y(k)  = 1 / (YTable (s_jo_ZigZag(k)) * aasf(row) * aasf(col))
			fdtbl_UV(k) = 1 / (UVTable(s_jo_ZigZag(k)) * aasf(row) * aasf(col))
			k+=1
		next
	next

	static as const ubyte head0(...) = { &HFF,&HD8,&HFF,&HE0,0,&H10,asc("J"),asc("F"),asc("I"),asc("F"),0,1,1,0,0,1,0,1,0,0,&HFF,&HDB,0,&H84,0 }
	put #1,, head0()
	put #1,, YTable()
	print #1, chr(1);
	put #1,, UVTable()
	dim as const ubyte head1(...) = { &HFF,&HC0,0,&H11,8,cast(ubyte, height shr 8),cast(ubyte, height and &HFF),cast(ubyte, width_ shr 8),cast(ubyte, width_ and &HFF),3,1,&H11,0,2,&H11,1,3,&H11,1,&HFF,&HC4,&H01,&HA2,0 }
	put #1,, head1()
	put #1,, std_dc_luminance_nrcodes()
	put #1,, std_dc_luminance_values()
	print #1, chr(&H10);
	put #1,, std_ac_luminance_nrcodes()
	put #1,, std_ac_luminance_values()
	print #1, chr(1);
	put #1,, std_dc_chrominance_nrcodes()
	put #1,, std_dc_chrominance_values()
	print #1, chr(&H11);
	put #1,, std_ac_chrominance_nrcodes()
	put #1,, std_ac_chrominance_values()
	static as const ubyte head2(...) = { &HFF,&HDA,0,&HC,3,1,0,2,&H11,3,&H11,0,&H3F,0 }
	put #1,, head2()

	dim as const ubyte ptr imageData = cast(const ubyte ptr,data_)
	dim as integer DCY=0, DCU=0, DCV=0
	dim as long bitBuf=0, bitCnt=0
	dim as integer ofsG = iif(comp > 1, 1, 0), ofsR = iif(comp > 1 , 2 , 0)
	for y as integer = 0 to height-1 step 8
		for x as integer= 0 to width_-1 step 8
			dim as single YDU(63), UDU(63), VDU(63)
			dim pos_ as integer=0
			for row as integer= y to y+7
				for col as integer= x to x+7
					dim p as integer = row*width_*comp + col*comp
					if row >= height then p -= width_*comp*(row+1 - height)
					if col >= width_ then p -= comp*(col+1 - width_)

					dim as single b = imageData[p+0], g = imageData[p+ofsG], r = imageData[p+ofsR]
					YDU(pos_)=+0.29900f*r+0.58700f*g+0.11400f*b-128
					UDU(pos_)=-0.16874f*r-0.33126f*g+0.50000f*b
					VDU(pos_)=+0.50000f*r-0.41869f*g-0.08131f*b
					pos_+=1
				next
			next

			DCY = jo_processDU(bitBuf, bitCnt, YDU(), fdtbl_Y(), DCY, YDC_HT(), YAC_HT())
			DCU = jo_processDU(bitBuf, bitCnt, UDU(), fdtbl_UV(), DCU, UVDC_HT(), UVAC_HT())
			DCV = jo_processDU(bitBuf, bitCnt, VDU(), fdtbl_UV(), DCV, UVDC_HT(), UVAC_HT())
		next
	next

end function

screenres 800,600,32
line (30,30)-(300,300),rgb(0,0,255),bf
circle (400,150),100,rgb(255,0,0),,,,f
print "Test"
sleep
screenlock
jo_write_jpg "picture.jpg", screenptr, 800,600, 4, 99
screenunlock
Last edited by angros47 on Aug 27, 2022 13:21, edited 1 time in total.
UEZ
Posts: 988
Joined: May 05, 2017 19:59
Location: Germany

Re: Saving a picture in jpeg format (pure FreeBasic, no external libraries)

Post by UEZ »

Works properly in x86 mode but not for x64 (type mismatch error).

You must change line 251 from integer to long

Code: Select all

dim as long bitBuf=0, bitCnt=0
Thanks for sharing it.

Does it work only for screen?
angros47
Posts: 2323
Joined: Jun 21, 2005 19:04

Re: Saving a picture in jpeg format (pure FreeBasic, no external libraries)

Post by angros47 »

Thank you, edited it.

The routine accepts a pointer to image data as input: in the example, I used screenptr that is the pointer to the graphic screen, but you can also use a pointer to any other graphic buffer (remember that buffers created with imagecreate have a header before image data, you must adjust the pointer accordingly)

The fifth parameter is the number of bytes per pixel: it can be 1 (for grey scale images: it is not a format used by FreeBasic, but can be implemented in indexed color mode with proper palettes), 3 (1 byte for each value of red, green and blue) or 4 (so each pixel is a long word in memory: FreeBasic uses the 4th byte for alpha value, the routine ignores it since jpg doesn't support alpha channel)

Also, the original routine expected data to be in RGB format, I modified it by swapping the red and blue channels since FreeBasic uses BGR format internally
angros47
Posts: 2323
Joined: Jun 21, 2005 19:04

Graphic output in CGI scripts

Post by angros47 »

Here is another application:

Code: Select all

#include "fbgfx.bi"
screencontrol FB.SET_DRIVER_NAME, "null"

Print !"Content-type:image/jpeg\n"

screenres 800,600,32
line (30,30)-(300,300),rgb(0,0,255),bf
circle (400,150),100,rgb(255,0,0),,,,f
print "Test"

screenlock

open cons for output as #1
dim as integer result = jo_write_jpg_to_func(screenptr, 800,600, 4, 90)
close #1

screenunlock
Compile it as a CGI script, put it in a server that supports CGI (in Linux it can be done by putting it in a subdirectory named 'cgi-bin' and running the command "python3 -m http.server --cgi"), then try accessing it with a browser: the browser will show the graphic output of the FreeBasic program.

So, FreeBasic can produce not just text-only CGI scripts, but also graphical scripts
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Saving a picture in jpeg format (pure FreeBasic, no external libraries)

Post by D.J.Peters »

UEZ wrote: Aug 27, 2022 12:41Does it work only for screen?
not all image widths are supported
FreeBASIC image buffers have a scanline (width) a multiply of 16 bytes for example in 4 byte per pixel mode
width must be a multiply of 4 pixels (4byte * 4pixel=16 bytes) 4,8,12,16,20 ... not allowed widths are: 5,6,7,9,10,11,13,14,15,17,18,19 ...

@angros47 do you post a jpg reader/decoder also ?

Joshy
angros47
Posts: 2323
Joined: Jun 21, 2005 19:04

Re: Saving a picture in jpeg format (pure FreeBasic, no external libraries)

Post by angros47 »

No, I haven't translated a jpeg reader, only the encoder. Although I remember there already was a jpeg decoder on this forum, translated by you:

viewtopic.php?t=15284
Post Reply