Shrinking a 1024x768 to 320x240 ?

Go To Last Post
99 posts / 0 new

Pages

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

Pages