Shrinking a 1024x768 to 320x240 ?

Go To Last Post
99 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys,

Does anyone know on how to shrink a 1024x768 photo into 320 x 240 TFT LCD ?
thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A lot of software can do this:
Photoshop
Paint.NET
MS Paint
.
.

If that is nor what you are looking for, then please be specific about what hardware the resizing will run on, what operating system (if any), if this is to be incorporated into some firmware and if so what programming language used etc etc..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to shrink the photo from sdcard with the MCU not with PC...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since you made no specification of the other circumstances I asked for: OK. Bye.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1024 / 320 (and 768 / 240) is 3.2

So you need to take the colour information from a 3.2 by 3.2 grid of pixels to make a single pixel in the output image.

Of course 0.2 of a pixel is quite a tricky concept ;-)

One simple technique would simply be to just use 3x3 grids of pixels but 1024x768 divided by 3 is 341x256 which is a little larger than your 320x240 display area.

If you were willing to simply crop and lose the edges then this might be workable still. In the X there are 21 too many pixels and in the Y there are 16 too many. So start the equivalent of ( 10,8 ) into the picture which, because of the /3 is (30,24).

IF you really want a /3.2 scaling you will likely want to employ error diffusion. A simple technique is Floyd-Steinberg.

One thing to bear in mind is how much CPU time you are willing to dedicate to this task. If these are just to show "thumbnails" of the larger images statically you can take a second or two do the scaling and no one will probably mind too much. If however these were frames of animation to be shown at 5 to 10 frames per second the time you have available to scale is much much less and you may need to make compromises.

One very simply compromise is that /4 on a binary computer is MUCH easier than /3. So if you were willing to scale the pictures to 1/4 their size (that is 1024x768 -> 256x192) then you could simply average 4x4 grids of source pixels.

For each output pixel you go 4 across and 4 down adding up the colour values of 16 pixels then divide the sum by 16. Watch for integer overflow but note that a /16 can even be easier than a /2 or /4 in some cases as it can involve nybble swaps.

Also consider whether this is mono or colour and how many bits per pixel there are either for the Y or the RGB.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to divide the image into blocks of 3.2 * 3.2 pixels, find the average colour value for each block. How you actually do that is up to you, and depends on how much memory you have available and how much time you want to spend on it(both your time and the AVRs time).
Let's say you want the top left pixel of your 320 * 240 image: For each of R, G and B, add the values of the first three pixels on the top row of the larger display, then add 0.2 of the value of the next pixel. Repeat for the 1st three pixels of the next 2 rows. Finally, add in 0.2 of the value of the first 3 pixels on the 4th row, and then 0.4 of the 4th pixel on the 4th row. Now find the average by dividing all the sums(R, G and B) by 3.2. When you move to the next block, things will be more complicated, as now you need 0.8 of the first values and 0.4 of the last. You get the idea. It will be horribly slow.
If you have sufficient memory, you could duplicate each pixel of the larger image 4 times, so that you have 5 of each. Then you can average 16 by 16 pixel blocks of this extra large image.

Maybe there's an easier way, but I can't think of it right now.

Much simpler to take Johan's advice and do it on the PC first. Added to which you only need a tenth of the memory space to store a 320 * 240 image.

Four legs good, two legs bad, three legs stable.

Last Edited: Thu. Apr 24, 2014 - 11:53 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Must learn to type faster.....

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Two really good messages to add to the image processing algos examples directory. Where was that again?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Where was that again?

Right there at the place where you created it, Bob..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To clawson, thank you for the explaination, I'll try to understand and translate it into code...
I saw this one :
http://tech-algorithm.com/articles/nearest-neighbor-image-scaling/

Can I use it ? any experiences ?
thanks
=======

clawson wrote:
1024 / 320 (and 768 / 240) is 3.2

So you need to take the colour information from a 3.2 by 3.2 grid of pixels to make a single pixel in the output image.

Of course 0.2 of a pixel is quite a tricky concept ;-)

One simple technique would simply be to just use 3x3 grids of pixels but 1024x768 divided by 3 is 341x256 which is a little larger than your 320x240 display area.

If you were willing to simply crop and lose the edges then this might be workable still. In the X there are 21 too many pixels and in the Y there are 16 too many. So start the equivalent of ( 10,8 ) into the picture which, because of the /3 is (30,24).

IF you really want a /3.2 scaling you will likely want to employ error diffusion. A simple technique is Floyd-Steinberg.

One thing to bear in mind is how much CPU time you are willing to dedicate to this task. If these are just to show "thumbnails" of the larger images statically you can take a second or two do the scaling and no one will probably mind too much. If however these were frames of animation to be shown at 5 to 10 frames per second the time you have available to scale is much much less and you may need to make compromises.

One very simply compromise is that /4 on a binary computer is MUCH easier than /3. So if you were willing to scale the pictures to 1/4 their size (that is 1024x768 -> 256x192) then you could simply average 4x4 grids of source pixels.

For each output pixel you go 4 across and 4 down adding up the colour values of 16 pixels then divide the sum by 16. Watch for integer overflow but note that a /16 can even be easier than a /2 or /4 in some cases as it can involve nybble swaps.

Also consider whether this is mono or colour and how many bits per pixel there are either for the Y or the RGB.

[url][/url]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have made this far, but I need to convert to 320x240 in PC first before I can use the picture with this code (on MCU), please have a look, thank you

//Function reading 262K file
  void LCD_BMP_reading_shrink(char filename[120])
 {
     char temp_buffer[100],line[512];
	int count,z,bmpData,bmpAddr;
	int x = 0;
	int i,y = 0;
	int xx, yy;
    uint8_t hdr[0x28];
	UINT bytesread;

	
    uint8_t hdr_256[0x36];
    static uint16_t w[256];
    uint32_t off;

	 res = f_open(&fsrc, filename, FA_READ);
						  
						  f_read(&fsrc, hdr_256, sizeof(hdr_256), &bytesread); // Read header
						  
						  off = *((uint32_t *)&hdr_256[0x0A]); // offset to rasters
						 
						  xx = *((uint32_t *)&hdr_256[0x12]); // X pixels
						  
						  yy = *((uint32_t *)&hdr_256[0x16]); // Y pixels
						   
						  f_lseek(&fsrc, off); // Seek to the data
						   
						  for(y=0; y> 8) | ((rgb & 0x00FC00) >> 5) | ((rgb & 0x0000F8) >> 3);
						 
						      LCD_SetPoint(y, x, rgb);
						    } // x
						  } // y
						   
						  f_close(&fsrc); 
 }
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

3.2 px isn't that hard.

Your image is 1024 x 768.

To figure each pixel of your 320x240 image, average the r, g and b's of a 4x4 pixel area of the original image.

The trick is in deciding which 16 source pixels to use for each dest pixel. Just take the dest pixel position, multiply it by 3.2 and truncate to find the source pixel position. Or, as I'm want to do to avoid floating point, add 32 and divide by 10.

Petulantly yours

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

if you want it quick just take pixel :
0,3,6,9,12,16,19,22,25,28,32 (every 5'th time add 4 else 3) make it with a counter or use that 3.2 is 16/5
in both x and y direction and forget about the rest of the pixels

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

if you want it a tad better do the same but use the pixels next to it as well. direct as a sum and div by 9 or something like this:
20 30 20
30 56 30
20 30 20
and then div with 256 same as move a byte (>>8 )

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Way cool. Its like auditing a 5000 level class in image processing.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
add 32 and divide by 10.

Multiplying by 32 might be better...

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bianchi77 wrote:
I need to convert to 320x240 in PC first

If you're doing the conversion on the PC then, surely, there are plenty of PC image manipulation tools to do that :?:

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is, and I want to convert it inside MCU, thanks guys for the suggestions, I'll give a try...
I'll get back after I've tried with the code..

awneil wrote:
bianchi77 wrote:
I need to convert to 320x240 in PC first

If you're doing the conversion on the PC then, surely, there are plenty of PC image manipulation tools to do that :?:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Like this ?

for(y=0; y

sparrow2 wrote:
if you want it quick just take pixel :
0,3,6,9,12,16,19,22,25,28,32 (every 5'th time add 4 else 3) make it with a counter or use that 3.2 is 16/5
in both x and y direction and forget about the rest of the pixels

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Like this ?

But that doesn't implement the algorithm sparrow2 suggested? He said that instead of incrementing +3, +3, +3, +3, +3, +3... you should increment +3, +3, +3, +3, +4, +3... so that every 5th increment is 3+1. Perhaps the easiest way to achieve that is

int n;
for(x=0, n=0; x

I'd be tempted to call your "xx" something like "w" or "width". Having both x and xx variables makes the code confusing and difficult to read. ("yy" = "h"/"height" too).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
int n;
for(x=0, n=0; x

do I need

int n;
for(y=0, n=0; y

as well ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That was the plan, yes.

There are two ways to do this.

1) Either just pick up every 3rd/4th pixel and use that - this is the very quick method suggested by sparrow2

or

2) combine methods: use the 3/4 stepping but also sum/average a complete 3x3 or 4x4 grid at each step

One thing I wouldn't do is develop this on an AVR. I'd write a small C program in Windows that can bitblt() the result to a client window area and see what actually works OK. Does the 3/4 step ignoring all other pixels look OK or do you need to use the 3x3/4x4 averaged grid method? Also just getting the grids/steps right is much easier if you can instantly visualise the results on a PC. One technique I've used in the past is to display both source and destination images. Have some form of user input so you can step across the X or down the Y to see the result being built and also, to make sure you are using the right source pixels each time, having read the source write back to your stored copy and display it - turning the pixels you just read to red or green or something. That way you can see if you are inadvertently overlapping your source squares/rectangles or anything like that.

(actually this is such an interesting challenge I might try it myself).

Obviously if you develop it on a PC you should find (if you stick with stdint.h types) that you can just build the same code for an AVR and it will work there too.

That leads to another possibility. I'll bet you aren't the first person who ever wanted to scaled 1024x768 to 320x240 so I'll bet there's code out there on the net already doing this. Pick it up, build it for your PC display program, when that works take the algorithm code to your AVR where you know it works and any other "wrong display" problems are something else and not a fault in the scaling code as such.

EDIT: actually I typed "scale 1024x768 to 320x240 code" into Google and the top hit was this thread- maybe you are the first??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've tried to shrink stuff down and the problem with just copying every 4th pix to the dest frame is that lines that are 1 pix wide and not on that magic 4pix boundary dont get copied. They just disappear. So the average trick is needed.

How does the 1024x768 get written to the sd card? Why cant it get shrunk to 320x240 before writing? I like to try to visualize the gizmo in use.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I totally agree, Bob. Some sort of averaging is needed.
I think maybe Torby had the best solution yet that trades off speed and accuracy in his post I quote below puctuation what do I care for punctuation.

The downside of such a method is that some pixels will have more "influence" than others, but I doubt that it'll be that noticeable.

Torby wrote:
3.2 px isn't that hard.

Your image is 1024 x 768.

To figure each pixel of your 320x240 image, average the r, g and b's of a 4x4 pixel area of the original image.

The trick is in deciding which 16 source pixels to use for each dest pixel. Just take the dest pixel position, multiply it by 3.2 and truncate to find the source pixel position. Or, as I'm want to do to avoid floating point, add 32 and divide by 10.

Petulantly yours

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does anyone have experience of the Win32 LoadImage() API?

I am trying:

   case IDM_FOPEN:
	{
	    OPENFILENAME ofn;
	    char szFileName[MAX_PATH] = "";

	    ZeroMemory(&ofn, sizeof(ofn));

	    ofn.lStructSize = sizeof(ofn); 
	    ofn.hwndOwner = hwnd;
	    ofn.lpstrFilter = "BitmapFiles (*.bmp)\0*.bmp\0All Files (*.*)\0*.*\0";
	    ofn.lpstrFile = szFileName;
	    ofn.nMaxFile = MAX_PATH;
	    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
	    ofn.lpstrDefExt = "bmp";

	    if(GetOpenFileName(&ofn))
	    {
             MessageBox(hwnd, szFileName, "Filename", MB_OK);
             bmpFILE = LoadImage(NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
	    }

The MessageBox confirms that the BMP file I just chose is the correct one but after the LoadImage the bmpFILE (which is an HBITMAP - don't ask!) is always NULL?! I don't need anything more than LR_LOADFROMFILE in the fuLoad parameter do I?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I need to add:
For a good result avoid using jpeg pictures those "false" edges will make it look kind of odd.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just to note that after a bit of googling I found others who got NULL from LoadImage() and yet GetLastError() also gave 0. In both cases they simply loaded the .BMP into Windows Paint then saved it again and that fixed things. That worked for me too. I had initially resized/cropped the image I was trying to use with Gimp and while it was usable as a 24bit RGB BMP in most places LoadImage() didn't like it.

I also found that I'd forgotten to InvalidateRect() to force a WM_PAINT to get it drawn on the client area. So now fixed and I can load and display a 1024x768 image so now to try scaling it....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does Mr Bianchi have an example bmp? Is it rgb? A photo? Graphics?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The 1024x768 I'm using:

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Whats all those white specs in the eyes? Rooting in the garden for moles?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is probably obvious, but perhaps worth mentioning.

If one is looking for 1 pixel wide lines, and doing a four pixel average for compression, then the threshold for calling the pixel ON is >= 25 %, (assuming a blank background, etc.). Hence in practice one might set the threshold quite low.

The nice thing about doing the test program on a PC is that one could have a slider for the threshold to call a pixel On/Off, and watch the lines appear / disappear as one moves the threshold slider.

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Quote:
add 32 and divide by 10.

Multiplying by 32 might be better...

Good point. When taking advice from a dyslexic brat, always check his math.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried :

	  //262K picture
                        delay_ms(1500);
					
	 res = f_open(&fsrc, "test31.bmp", FA_READ);

 f_read(&fsrc, hdr_256, sizeof(hdr_256),&bytesread); // Read header
  off = *((uint32_t *)&hdr_256[0x0A]); // offset to rasters
						 
  xx = *((uint32_t *)&hdr_256[0x12]); // X pixels
  yy = *((uint32_t *)&hdr_256[0x16]); // Y pixels
						  
						   
						  f_lseek(&fsrc, off); // Seek to the data
						   
						 for(y=0, n=0; y> 8) | ((rgb & 0x00FC00) >> 5) | ((rgb & 0x0000F8) >> 3);
								 
								      LCD_SetPoint(y, x, rgb);
								    } // x
						  } // y
						   
						  f_close(&fsrc); 
						  delay_ms(2000);

Please correct me if I missed something here, thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd like to see the picture unless its a picture of your girlfriends hoohoo.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bobgardner wrote:
I'd like to see the picture unless its a picture of your girlfriends hoohoo.

I got a picture already, but not yet right...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bobgardner wrote:
I'd like to see the picture unless its a picture of your girlfriends hoohoo.

I apologise on behalf of Bob.
The correct term, so my daughter, who is a trained nurse, informs me, is "floo floo".

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

DocJC wrote:
This is probably obvious, but perhaps worth mentioning.

If one is looking for 1 pixel wide lines, and doing a four pixel average for compression, then the threshold for calling the pixel ON is >= 25 %, (assuming a blank background, etc.). Hence in practice one might set the threshold quite low.

The nice thing about doing the test program on a PC is that one could have a slider for the threshold to call a pixel On/Off, and watch the lines appear / disappear as one moves the threshold slider.

JC


I had assumed that the OP was using a colour display.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes it's 262K colour display,
I want to display :

on LCD I have :

I used this function for displaying it,

   //262K picture
                        delay_ms(1500);
               
    res = f_open(&fsrc, "test31.bmp", FA_READ);

 f_read(&fsrc, hdr_256, sizeof(hdr_256),&bytesread); // Read header
  off = *((uint32_t *)&hdr_256[0x0A]); // offset to rasters
                  
  xx = *((uint32_t *)&hdr_256[0x12]); // X pixels
  yy = *((uint32_t *)&hdr_256[0x16]); // Y pixels
                   
                     
                    f_lseek(&fsrc, off); // Seek to the data
                     
                   for(y=0, n=0; y> 8) | ((rgb & 0x00FC00) >> 5) | ((rgb & 0x0000F8) >> 3);
                        
                              LCD_SetPoint(y, x, rgb);
                            } // x
                    } // y
                     
                    f_close(&fsrc);
                    delay_ms(2000); 

Any clues guys ?

thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First thing I notice is that you're using the same variable, n, in both the outer loop(y) and the inner loop(x). This is surely not going to work.

And you're using the same x and y, unless I'm mistaken, for both the 1024 by 768 and the 320 by 240.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How much RAM do you have available for this task?

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

so I have to separate the variable ?can you give me a clue in code ? RAM inside LCD is 191 Kbytes
Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
//262K picture
uint16_t destx;
uint16_t desty;

delay_ms(1500);
			   
res = f_open(&fsrc, "test31.bmp", FA_READ);

f_read(&fsrc, hdr_256, sizeof(hdr_256),&bytesread); // Read header
off = *((uint32_t *)&hdr_256[0x0A]); // offset to rasters
				 
sourcewidth = *((uint32_t *)&hdr_256[0x12]); // X pixels
sourceheight = *((uint32_t *)&hdr_256[0x16]); // Y pixels
				   
					 
f_lseek(&fsrc, off); // Seek to the data
destx = 0;
desty = 0;
for(y = 0, ny = 0; y < sourceheight; ny += 3, ny++)
					 
	{
	if (ny == 5)
		{
		y++;
		ny = 0;
		}
	for(x = 0,nx = 0; x < sourcewidth; x += 3,nx++)
		{
		uint32_t rgb;
		if (nx == 5)
			{
			x++;
			nx = 0;
			}
		f_read(&fsrc, &rgb, 3, &bytesread); // Read pixel B G R
		// RRRRRRRRGGGGGGGGBBBBBBBB 8:8:8
		//         RRRRRGGGGGGBBBBB 5:6:5
		rgb = ((rgb & 0xF80000) >> 8) | ((rgb & 0x00FC00) >> 5) | ((rgb & 0x0000F8) >> 3);
		LCD_SetPoint(desty, destx, rgb);
		destx++;
		if(destx == 320)
			{
			destx = 0;
			desty++;
			}
		}
	}
f_close(&fsrc);
delay_ms(2000); 

Something like this(untested)

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And I meant how much RAM for the code to use. Because once you find out how crappy it looks taking every 3rd pixel, you'll be wanting to do some averaging, and there might be faster ways of doing that if you have a few K of RAM available.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll offer my opinion that a screen full of blue pixels is not the most detailed test pattern for a reduction algorithm. How can you tell if the row and column you want to see is accidentally deleted? That's why I asked what your test picture was. I will also offer my idea that if I had to do this, I would open the file, read 4 lines of the picture to ram, walk the 4x4 averager/filter across the line, writing the resulting 320 pix for the dest frame to the sd card. Repeat 240 times. Read 320x240 image back from sdcard to lcd. Whew. Lots of work.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The kinda official way to downsize an image is to low pass filter the complete image and *then* to decimate it. The thing that needs to happen is that the averager (if that's your chosen filter) should not just filter the four lines you're trying to compress into one, but should include the lines to either side.

If you don't average, you *will* get alias 'jaggies' in the final image. Whether this is acceptable can only be decided by you, but such images look excessively edgy and high-frequencies are incorrectly emphasised by the aliasing.

Because your divide ratio is not an exact integer (unless you slice part of the image away to make it exact) you'll still get jaggies if you use the naive 4-4-4-5-4-4-4-5 sampling - again, your decision as to whether that is acceptable.

The clean way to arbitrarily down-scale an image is to upscale it first - insert zeros between the original picture pixels - until it's a size that shares a common multiple with the final image (e.g. if you're going to 7/8ths the original size, you'd upscale by a factor of 7) and then low pass filter the result to leave no alias frequencies. Then decimate the image for the final image - in this case, take every eighth pixel.

That's obviously incredibly time consuming though there are optimisations that help with the filtering, and it takes a lot of memory... sometimes you just have to be pragmatic.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I got :

with this function :

	res = f_open(&fsrc, "test31.bmp", FA_READ);
			
			f_read(&fsrc, hdr_256, sizeof(hdr_256),&bytesread); // Read header
			off = *((uint32_t *)&hdr_256[0x0A]); // offset to rasters
			            
			sourcewidth = *((uint32_t *)&hdr_256[0x12]); // X pixels
			sourceheight = *((uint32_t *)&hdr_256[0x16]); // Y pixels
			               
			               
			f_lseek(&fsrc, off); // Seek to the data
			destx = 0;
			desty = 0;
			for(y = 0, ny = 0; y < sourceheight; ny += 3, ny++)
			               
			   {
			   if (ny == 5)
			      {
			      y++;
			      ny = 0;
			      }
			   for(x = 0,nx = 0; x < sourcewidth; x += 3,nx++)
			      {
			      uint32_t rgb;
			      if (nx == 5)
			         {
			         x++;
			         nx = 0;
			         }
			      f_read(&fsrc, &rgb, 3, &bytesread); // Read pixel B G R
			      // RRRRRRRRGGGGGGGGBBBBBBBB 8:8:8
			      //         RRRRRGGGGGGBBBBB 5:6:5
			      rgb = ((rgb & 0xF80000) >> 8) | ((rgb & 0x00FC00) >> 5) | ((rgb & 0x0000F8) >> 3);
			      LCD_SetPoint(desty, destx, rgb);
			      destx++;
			      if(destx == 320)
			         {
			         destx = 0;
			         desty++;
			         }
			      }
			   }
				f_close(&fsrc);

what do I miss here ? thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Doremon - i'm more of a Hello Kitty fan. Oh, you mean the lcd..... I would normally use printf to dump out the loop values. You should see a pattern.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

probably like this ?

 printf("Dest y : ");printf(desty);NEXT_LINE;
 printf("Dest x : ");printf(destx);NEXT_LINE;
  printf("rgb : ");printf(rgb);NEXT_LINE;
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

printf(desty);

No. The variable desty does not contain a format string. In fact, it is not even a string - it is an integer value.

http://www.nongnu.org/avr-libc/u...
which leads to
http://www.nongnu.org/avr-libc/u...
where it is written

Quote:
The format string is composed of zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments.

Or just read about printf in your C textbook.

Same for destx and RGB.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
for(y = 0, ny = 0; y < sourceheight; ny += 3, ny++) 

should be

for(y = 0, ny = 0; y < sourceheight; y += 3, ny++) 

My typo. Sorry.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:

for(y = 0, ny = 0; y < sourceheight; ny += 3, ny++) 

should be

for(y = 0, ny = 0; y < sourceheight; y += 3, ny++) 

My typo. Sorry.


Ok,
I'll try, thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I made :

 char temp_buffer[100],line[512];
	int count,z,bmpData,bmpAddr;
	int x = 0;
	int i,y = 0;
	int xx, yy,ny,nx;
    uint8_t hdr[0x28];
	UINT bytesread;
    uint8_t hdr_256[0x36];
    static uint16_t w[256];
    uint32_t off,sourcewidth,sourceheight;

			    //262K picture
			uint16_t destx;
			uint16_t desty;
			
			delay_ms(1500);
			 LCD_Clear(Black);            
			res = f_open(&fsrc, filename, FA_READ);
			
			f_read(&fsrc, hdr_256, sizeof(hdr_256),&bytesread); // Read header
			off = *((uint32_t *)&hdr_256[0x0A]); // offset to rasters
			            
			sourcewidth = *((uint32_t *)&hdr_256[0x12]); // X pixels
			sourceheight = *((uint32_t *)&hdr_256[0x16]); // Y pixels
			               
			               
			f_lseek(&fsrc, off); // Seek to the data
			destx = 0;
			desty = 0;
//for(y = 0, ny = 0; y < sourceheight; ny += 3, ny++)
for(y = 0, ny = 0; y < sourceheight; y += 3, ny++)
			               
			   {
			   if (ny == 5)
			      {
			      y++;
			      ny = 0;
			      }
			    
			    for(x = 0,nx = 0; x < sourcewidth; x += 3,nx++)
			      {
			      uint32_t rgb;
			      if (nx == 5)
			         {
			         x++;
			         nx = 0;
			         }
			      f_read(&fsrc, &rgb, 3, &bytesread); // Read pixel B G R
			      // RRRRRRRRGGGGGGGGBBBBBBBB 8:8:8
			      //         RRRRRGGGGGGBBBBB 5:6:5
			      rgb = ((rgb & 0xF80000) >> 8) | ((rgb & 0x00FC00) >> 5) | ((rgb & 0x0000F8) >> 3);
			      LCD_SetPoint(desty, destx, rgb);
				  
				
			      
				  destx++;
			      if(destx == 320)
			         {
			         destx = 0;
			         desty++;
			         }
			      }
			   }
				f_close(&fsrc);
				delay_ms(2000);

I got :

Please let me know what I miss here ?
thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Although you are counting to every third pixel, you are just reading consecutive pixels from the large image. You need to either read and discard all the intermediate pixels, or fseek to the one you want. I have no idea as to which would be quicker, but with the code as it is, it would probably be easier to use the x and y values to calculate a new offset in the file to fseek to.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So every time you read the rgb values from the file you need to to calulate the offset within the file.
Have a new variable, pixeloffs, and do something like

pixeloff = offs + (y * 1024 * 3) + (x * 3); // Assuming three bytes per pixel
f_lseek(&fsrc, off); // Seek to the desired pixel
f_read(&fsrc, &rgb, 3, &bytesread); // Read pixel B G R 


 

Note that this works because the big image width is 1024. If it was some other width, you would need to work out the row size, as I believe rows are padded to be multiples of 4(?) bytes.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hmm.....try to understand...I'll get back later..thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
So every time you read the rgb values from the file you need to to calulate the offset within the file.
Have a new variable, pixeloffs, and do something like

pixeloff = offs + (y * 1024 * 3) + (x * 3); // Assuming three bytes per pixel
f_lseek(&fsrc, pixeloff); // Seek to the desired pixel
f_read(&fsrc, &rgb, 3, &bytesread); // Read pixel B G R 


 

Note that this works because the big image width is 1024. If it was some other width, you would need to work out the row size, as I believe rows are padded to be multiples of 4(?) bytes.

Edit: Corrected line above, the seek is to pixeloff, not offs.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
John_A_Brown wrote:
So every time you read the rgb values from the file you need to to calulate the offset within the file.
Have a new variable, pixeloffs, and do something like

pixeloff = offs + (y * 1024 * 3) + (x * 3); // Assuming three bytes per pixel
f_lseek(&fsrc, pixeloff); // Seek to the desired pixel
f_read(&fsrc, &rgb, 3, &bytesread); // Read pixel B G R 


 

then display those pixels into the LCD with LCD_Setpoint ? thanks
Note that this works because the big image width is 1024. If it was some other width, you would need to work out the row size, as I believe rows are padded to be multiples of 4(?) bytes.

Edit: Corrected line above, the seek is to pixeloff, not offs.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I hate to ask this lo level question, but we have to assume the drawing stuff works well and you can draw a box around the lcd and two vertical lines on the left and they actually show up as vertical lines on the left, not right, not horizontal, not diagonal? OK, good. Now we can use the lcd to look at the picture. How about cooking up a 320x240 bmp and test reading that? Looks ok? Great. I'd try 640x480 next.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had a chance to work a bit more on my Windows program to try various types of scaling but stopped after the first attempt because to these tired old eyes it actually looks pretty bloomin good without bothering to explore other options. This is the scaling I used:

    if (dispBmp) {
	    MemDCFILE = CreateCompatibleDC(hDC);
	    SelectObject(MemDCFILE, dispBmp );
		if (scaled != TRUE) {
		    GetObject( dispBmp, sizeof(BITMAP), &bm );
		    BitBlt( hDC, 10, 10, bm.bmWidth, bm.bmHeight, MemDCFILE, 0, 0, SRCCOPY );
		}
		else {
            HBITMAP hNewBmp;
			HDC hEditDC;
			int x,y;
            hNewBmp = CreateCompatibleBitmap(GetDC(hwnd), 320, 240);
			hEditDC = CreateCompatibleDC(GetDC(hwnd));
			SelectObject(hEditDC, hNewBmp);
			for (y=0; y<240; y++) {
				for (x=0; x<320; x++) {
					SetPixel(hEditDC, x, y, GetPixel(MemDCFILE, x * 3.2, y * 3.2));
				}
			}
		    BitBlt( hDC, 10, 10, 320, 240, hEditDC, 0, 0, SRCCOPY );
            DeleteObject(hNewBmp);
			DeleteDC(hEditDC);
        }
        DeleteDC(MemDCFILE);
    }

    EndPaint(hwnd, &ps);

As you can see all I do is step x,y for the dimensions of the destination image and set the output pixel (SetPixel()) to the pixel at GetPixel(x*3.2, y*3.2) from the source image.

As I say the result looks pretty darned good to me... though I suppose some of Amelia's more vertical whiskers have disappeared a bit?

For completeness I may try the 3,3,3,3,4... thing and also 3x3 or 4x4 averaged grids but, to be honest I don't see a lot of point.

Of course this "costs" a "* 3.2" operation but that doesn't matter on this multi-GHz PC ;-)

If anyone's interested I can upload the complete Pelles C project that created this Windows application.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That is suprisingly good.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So when a user mode app in windows calls the setpixel() sub in the linked in runtime lib, it calls a sub pointed to in the graphics driver, could be directx (whatever that is), GDI, the driver in the firmware of the graphics card. It could be doing some sort of antialiasing/smoothing/texturing. Who knows whats going on. Who even knows how many layers of api there are?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To Clawson, I wish I can do

GetPixel(MemDCFILE, x * 3.2, y * 3.2)

on my code...
I wish...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bobgardner wrote:
I hate to ask this lo level question, but we have to assume the drawing stuff works well and you can draw a box around the lcd and two vertical lines on the left and they actually show up as vertical lines on the left, not right, not horizontal, not diagonal? OK, good. Now we can use the lcd to look at the picture. How about cooking up a 320x240 bmp and test reading that? Looks ok? Great. I'd try 640x480 next.

no problem with 320x240, if I create first on PC and then copy to SD card,
have a look..
https://www.youtube.com/watch?v=P_Bvq7yXxIk

thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To John,

off = *((uint32_t *)&hdr_256[0x0A]); // offset to rasters
						 
xx = *((uint32_t *)&hdr_256[0x12]); // X pixels
  
yy = *((uint32_t *)&hdr_256[0x16]); // Y pixels
						  
						  
						  pixeloff = off + (y * 1024 * 3) + (x * 3); // Assuming three bytes per pixel

it's "off" not "offs", isn't it ?
thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Yes.

I have tried it, still the same, no luck :( ....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Post your actual code.

Quote:

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Post your actual code.
Quote:


Hi John,

Here's the code I used, please have a look and correct me if there's mistake, thanks

	int x = 0;
	int i,y = 0;
	int xx, yy,ny,nx;
    uint8_t hdr[0x28];
	UINT bytesread;
    uint8_t hdr_256[0x36];
    static uint16_t w[256];
    uint32_t off,sourcewidth,sourceheight,pixeloff;

			    //262K picture
			uint16_t destx;
			uint16_t desty;
			
              delay_ms(1500);			             LCD_Clear(Black);            
	res = f_open(&fsrc, filename, FA_READ);
					f_read(&fsrc, hdr_256, sizeof(hdr_256),&bytesread); // Read header
off = *((uint32_t *)&hdr_256[0x0A]); // offset to rasters
			            
sourcewidth = *((uint32_t *)&hdr_256[0x12]); // X pixels
sourceheight = *((uint32_t *)&hdr_256[0x16]); // Y pixels
			               
pixeloff = off + (y * 1024 * 3) + (x * 3); // Assuming three bytes per pixel
f_lseek(&fsrc, pixeloff); // Seek to the desired pixel			               
//f_lseek(&fsrc, off); // Seek to the data

destx = 0;
desty = 0;
//for(y = 0, ny = 0; y < sourceheight; ny += 3, ny++)
for(y = 0, ny = 0; y < sourceheight; y += 3, ny++)
			               
			   {
			   if (ny == 5)
			      {
			      y++;
			      ny = 0;
			      }
			    
   for(x = 0,nx = 0; x < sourcewidth; x += 3,nx++)
			      {
			      uint32_t rgb;
			      if (nx == 5)
			         {
			         x++;
			         nx = 0;
			         }
f_read(&fsrc, &rgb, 3, &bytesread); // Read pixel B G R
   // RRRRRRRRGGGGGGGGBBBBBBBB 8:8:8
   //         RRRRRGGGGGGBBBBB 5:6:5
rgb = ((rgb & 0xF80000) >> 8) | ((rgb & 0x00FC00) >> 5) | ((rgb & 0x0000F8) >> 3);
     LCD_SetPoint(desty, destx, rgb);
				  //sprintf(temp_buffer,"%.2d",rgb);printf(temp_buffer);printf("\n");
				
			      
				  destx++;
			      if(destx == 320)
			         {
			         destx = 0;
			         desty++;
			         }
			      }
			   }
				f_close(&fsrc);
				delay_ms(2000);

trying to fix identation, it's ok on my compiler... but change if I copy here....different size

Last Edited: Mon. Apr 28, 2014 - 08:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 int x = 0;
   int i,y = 0;
   int xx, yy,ny,nx;
    uint8_t hdr[0x28];
   UINT bytesread;
    uint8_t hdr_256[0x36];
    static uint16_t w[256];
    uint32_t off,sourcewidth,sourceheight,pixeloff;

             //262K picture
         uint16_t destx;
         uint16_t desty;
         
         delay_ms(1500);
          LCD_Clear(Black);           
         res = f_open(&fsrc, filename, FA_READ);
         
         f_read(&fsrc, hdr_256, sizeof(hdr_256),&bytesread); // Read header
         off = *((uint32_t *)&hdr_256[0x0A]); // offset to rasters
                    
         sourcewidth = *((uint32_t *)&hdr_256[0x12]); // X pixels
         sourceheight = *((uint32_t *)&hdr_256[0x16]); // Y pixels
                        
         f_lseek(&fsrc, off); // Seek to the start of the pixel data

         destx = 0;
         desty = 0;

         for(y = 0, ny = 0; y < sourceheight; y += 3, ny++)
                        
            {
            if (ny == 5)
               {
               y++;
               ny = 0;
               }
            
             for(x = 0,nx = 0; x < sourcewidth; x += 3,nx++)
               {
               uint32_t rgb;
               if (nx == 5)
                  {
                  x++;
                  nx = 0;
                  }
       pixeloff = off + (y * 1024 * 3) + (x * 3); // Assuming three bytes per pixel
         f_lseek(&fsrc, pixeloff); // Seek to the desired pixel                        

               f_read(&fsrc, &rgb, 3, &bytesread); // Read pixel B G R
               // RRRRRRRRGGGGGGGGBBBBBBBB 8:8:8
               //         RRRRRGGGGGGBBBBB 5:6:5
               rgb = ((rgb & 0xF80000) >> 8) | ((rgb & 0x00FC00) >> 5) | ((rgb & 0x0000F8) >> 3);
               LCD_SetPoint(desty, destx, rgb);
              //sprintf(temp_buffer,"%.2d",rgb);printf(temp_buffer);printf("\n");
              
              destx++;
               if(destx == 320)
                  {
                  destx = 0;
                  desty++;
                  }
               }
            }
            f_close(&fsrc);
            delay_ms(2000); 

But one more question. What display are you using? Does it have the abilty to auto-increment to the next pixel? All the 320 by 240 displays I've used have this function.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dangit, John.. Bianchi got the indentation (almost) right for once, and immediately you ruin it.. :wink:

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's because I copied and pasted his code into a text editor to modify it. The weird mixture of tabs and spaces creates massive chaos. I have a proper job to do and I can't be arsed to straighten it up.
If you look at the code I posted on the 26th at 12:56 you'll see that I did attempt to get the formatting right(for my preferred scheme) but it was back to usual with the next post from the OP, and complete with variable names like xx and yy.

John

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
But one more question. What display are you using? Does it have the abilty to auto-increment to the next pixel? All the 320 by 240 displays I've used have this function.

I don't know if it does,
It's SSD1289 320x240 262K colours

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A quick look at the datasheet reveals that it does.

Attachment(s): 

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To John,

There's a progress

I followed the code :

	int x = 0;
	int i,y = 0;
	int ny,nx;
    uint8_t hdr[0x28];
	UINT bytesread;
    uint8_t hdr_256[0x36];
    static uint16_t w[256];
    uint32_t off,sourcewidth,sourceheight,pixeloff;

			    //262K picture
			uint16_t destx;
			uint16_t desty;
			
			delay_ms(1500);
			 LCD_Clear(Black);            
	res = f_open(&fsrc, filename, FA_READ);
			
f_read(&fsrc, hdr_256, sizeof(hdr_256),&bytesread); // Read header
off = *((uint32_t *)&hdr_256[0x0A]); // offset to rasters
      
sourcewidth = *((uint32_t *)&hdr_256[0x12]); // X pixels
sourceheight = *((uint32_t *)&hdr_256[0x16]); // Y pixels
			               
           

			destx = 0;
			desty = 0;
//for(y = 0, ny = 0; y < sourceheight; ny += 3, ny++)
for(y = 0, ny = 0; y < sourceheight; y += 3, ny++)
			               
			   {
			   if (ny == 5)
			      {
			      y++;
			      ny = 0;
			      }
			    
	    for(x = 0,nx = 0; x < sourcewidth; x += 3,nx++)
			      {
			      uint32_t rgb;
			      if (nx == 5)
			         {
			         x++;
			         nx = 0;
			         }
 pixeloff = off + (y * 1024 * 3) + (x * 3); // Assuming three bytes per pixel
 f_lseek(&fsrc, pixeloff); // Seek to the desired pixel			               
 //f_lseek(&fsrc, off); // Seek to the data
   f_read(&fsrc, &rgb, 3, &bytesread); // Read pixel B G R
  // RRRRRRRRGGGGGGGGBBBBBBBB 8:8:8
     //         RRRRRGGGGGGBBBBB 5:6:5
 rgb = ((rgb & 0xF80000) >> 8) | ((rgb & 0x00FC00) >> 5) | ((rgb & 0x0000F8) >> 3);
 LCD_SetPoint(desty, destx, rgb);
				  				
			      
				  destx++;
			      if(destx == 320)
			         {
			         destx = 0;
			         desty++;
			         }
			      }
			   }
				f_close(&fsrc);
				delay_ms(2000);

Please let me know what do I miss here ? thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried another one :

on LCD :

It's diagonal, why is it ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
LCD_SetPoint(desty, destx, rgb);

Is this correct? It is, I think, more usual for x to be first:
i.e.

LCD_SetPoint(destx, desty, rgb); 

However, it looks to me as though something is out by a factor of two.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

So when a user mode app in windows calls the setpixel() sub in the linked in runtime lib, it calls a sub pointed to in the graphics driver, could be directx (whatever that is), GDI, the driver in the firmware of the graphics card. It could be doing some sort of antialiasing/smoothing/texturing. Who knows whats going on. Who even knows how many layers of api there are?

Bob the functions I use are GDI from the WIN32 API. It is possibly one of the best documented programming APIs on planet earth:

http://msdn.microsoft.com/en-us/...

There is nothing "hidden" in the driver or what it does. If Microsoft says it sets a pixel to COLOREF on a bitmap selected into a device context then it sets a pixel in a device context - nothing more.

Quote:

To Clawson, I wish I can do

I fear you aren't getting the point of my posts and my small example program. There is nothing on earth stopping you doing the exact equivalent of:

GetPixel(MemDCFILE, x * 3.2, y * 3.2) 

In fact, you probably don't even need to pass a pointer to a device context/memory buffer as you aren't going to be working on lots of them. As for implementing GetPixel(x,y). Yes I know you only have a 512 byte sector buffer for the file read and yes, it may take some time to work out where in a file pixel (x,y) is then fseek() to that place and fread() the data (if you are lucky it's in the same sector you just read and will be buffered anyway - especially if you work across the X) but I would not try to do everything in huge cascades of nested for(x)/for(y) loops. Instead I would implement a GetPixel() and simply make sure that when you GetPixel(123,456) it really does return the colour of the pixel at that location. Similarly I would implement SetPixel() and then the conversion really does become as simple as:

         for (y=0; y<240; y++) {
            for (x=0; x<320; x++) {
               SetPixel(hEditDC, x, y, GetPixel(MemDCFILE, x * 3.2, y * 3.2));
            }
         }

Now I'll agree that this is not efficient code but it lets you work on the high-level design of the function. You can try other techniques for gathering the source pixels (and possibly averaging) and see how the results look. When you have found the "best looking" solution you now begin to look at optimisations for it that work best in a 512 byte sector buffer in the limited RAM of an AVR.

But do the high level design work first. Oh and did I mention that it would be 10 times easier to work on this in a PC program than on the limited resource hardware of an AVR?

BTW when you think about what my code is doing:

            for (x=0; x<320; x++) {
               SetPixel(hEditDC, x, y, GetPixel(MemDCFILE, x * 3.2, y * 3.2));
            }

it will be:

x      0    1    2    3    4    5    6    7    8    9    10
x*3.2  0    3.2  6.4  9.6  12.8 16  19.2  22.4 25.6 28.8 32
int(N) 0    3    6    9    12   16  19    22   25   28   32
+N     0    +3   +3   +3   +3   +4  +3    +3   +3   +3   +4 ...

So (I guess I'm a bit slow!) this IS just implementing the 3,3,3,3,4,3,3,3,3,4... pattern. As such the AVR does NOT need to do floating point "* 3.2" operations. Just doing the sourceX+3 thing with N==5 leading to sourceX+3+1 would have the same effect.

Of course now I have my basic GetPixel and SetPixel I can try replacing the *3.2 stuff with exactly that to verify that the integer version leads to the same result (it will).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm..
Should it be N == 4 ?

Although I don't see how that would have the observed effect.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Quote:
LCD_SetPoint(desty, destx, rgb);

Is this correct? It is, I think, more usual for x to be first:
i.e.

LCD_SetPoint(destx, desty, rgb); 

However, it looks to me as though something is out by a factor of two.


yea, that's correct, because if I reverse it, I have a reversed picture...

LCD_SetPoint(desty, destx, rgb); 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Hmm..
Should it be N == 4 ?

Although I don't see how that would have the observed effect.


I'll give a try and see what happens
thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 if (ny == 5) and  if (nx == 5)

try with if (ny == 4) and if (nx == 4) ?

There are four blue stripes on diagonal now....I'm not sure it's from there...?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you 100% sure that the image you are using is 1024 by 768?

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Are you 100% sure that the image you are using is 1024 by 768?

100% sure for the size, it is 1024 by 768...something missing on the code ? thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW I changed my code to use the integer version of 33334 stepping:

HBITMAP hNewBmp;
HDC hEditDC;
int x, y, n, m, destx, desty;
hNewBmp = CreateCompatibleBitmap(GetDC(hwnd), 320, 240);
hEditDC = CreateCompatibleDC(GetDC(hwnd));
SelectObject(hEditDC, hNewBmp);
n = 0;
m = 0;
destx = 0;
desty = 0;
for (y=0; y<768; y+=3) {
	for (x=0; x<1024; x+=3) {
		SetPixel(hEditDC, destx, desty, GetPixel(MemDCFILE, x, y));
		destx++;
		m++;
		if (m == 5) {
			x++;
			m =0;
		}
	}
	destx = 0;
	desty++;
	n++;
	if (n == 5) {
		y++;
		n = 0;
	}
}
BitBlt( hDC, 10, 10, 320, 240, hEditDC, 0, 0, SRCCOPY );
DeleteObject(hNewBmp);
DeleteDC(hEditDC);

and the visual result was identical.

The structure of this is very similar to what you are attempting except that I post increment n/m whereas you pre-increment.

Another thought about your data - what file format is it? If 24 bit RGB BMP and accessing the pixel data directly then apart from the obvious "upside down thing" in Windows BMP remember about the padding to 32 bit boundary though I would have thought 1024 wide images hit this naturally anyway as 1024 * 3 is 3072 and 3072 / 4 is 768 which is an integer multiple.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

to clawson,

for (y=0; y<768; y+=3) {
   for (x=0; x<1024; x+=3) { 

I don't understand...how to relate it with my code ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Another thought about your data - what file format is it?

It's 24 bit BMP RGB 1024x768

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I don't understand...how to relate it with my code ?


You use:

for(y = 0, ny = 0; y < sourceheight; y += 3, ny++)
       for(x = 0,nx = 0; x < sourcewidth; x += 3,nx++)

I chose not to mix the n/m stuff in with the outer for() loops (though I guess I could have) and in your code sourceheight=768 and sourcewidth=1204 so your loops really say:

for(y = 0,; y < 768; y += 3)
       for(x = 0; x <1024; x += 3)

Unless you can spot it I think we have identical code in this sense.

Quote:
It's 24 bit BMP RGB 1024x768

Yup I realised that from studying your code some more (I did find hdr_256 to be quite a confusing name though!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I took a 320 by 240 image, displayed it on my LCD, then displayed a scaled version(works out at 100 by 75).
This is what it looks like. Sorry about the terrible photo, it's just a crappy phone camera picture, and there's some sort of moire pattern artifact going on. It actually looks pretty good in real life.
The scaled image is upside down, you say? Yes, it is. On the big picture I read the bitmap backwards, as Windows saves from the bottom up. On the scaled image, I didn't want to complicate things that much.

Attachment(s): 

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void ScaleIt(uint32_t FlashAddr)
{
uint8_t buffer[64];
uint32_t FileSize;
uint32_t BitmapOffset;
uint32_t BitmapWidth;
uint32_t BitmapHeight;
uint32_t RowSize;
uint32_t colour;
uint32_t scalex, scaley;
uint32_t pixeloffs;
TFT_SetBotRight(319,240);	
DataFlashReadBlock(FlashAddr, buffer, 64);		// Read the header info
FileSize = (buffer[2]) | (buffer[3] << 8) | (buffer[4] << 16) | (buffer[5] << 24); // Get the file size
BitmapOffset = (buffer[10]) | (buffer[11] << 8) | (buffer[12] << 16) | (buffer[13] << 24);	// Get the offset to pixel data
BitmapWidth = (buffer[18]) | (buffer[19] << 8) | (buffer[20] << 16) | (buffer[21] << 24);   // Get the bitmap width
BitmapHeight = (buffer[22]) | (buffer[23] << 8) | (buffer[24] << 16) | (buffer[25] << 24);  // and the height
RowSize = ((24 * BitmapWidth + 31) / 32) * 4;			// Work out the row size

for(scaley = 0; scaley < 75; scaley++)
	{
	for(scalex = 0;scalex < 100; scalex++)
		{
		pixeloffs = BitmapOffset + ( (scaley * 32 / 10) * RowSize) + (scalex * 32 / 10) * 3;
		TFT_SetTopLeft(scalex, scaley);
		DataFlashReadBlock(pixeloffs, &colour, 3);		
		TFT_WritePixel(colour);	
		}	
	}
}

My bitmpap is simply stored in a flash chip, rather than being part of a filing system, but the general principle is the same.

And the reason I didn't start out with 1024 by 768 is that my Flash chip isn't quite big enough.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It works already, thanks guys..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Already?

:D

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And you shrunken image looks nice?

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Already?

:D

Yes it did, thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Torby wrote:
And you shrunken image looks nice?

Yes it does,
have a look on youtube, after the green and white box are 1024x768 shrunken

https://www.youtube.com/watch?v=P3rlm3_uV0k

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting background music choice - thank goodness it doesn't sound like a 70's porn video...

.. oh wait a minute!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVR digital picture frame. Perhaps it should appear on hackaday?

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Bianchi77, we want to know what you did that finally fixed your image shrinking code!

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Bianchi77, we want to know what you did that finally fixed your image shrinking code!

You haven't figured out bianchi77's M.O. yet, John?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Quote:
Bianchi77, we want to know what you did that finally fixed your image shrinking code!

You haven't figured out bianchi77's M.O. yet, John?

Obviously not.
I don't think I'll be helping him/her again.

Four legs good, two legs bad, three legs stable.